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,6 +93,8 @@ struct SerialState {
93 int it_shift; 93 int it_shift;
94 }; 94 };
95 95
  96 +static void serial_receive_byte(SerialState *s, int ch);
  97 +
96 static void serial_update_irq(SerialState *s) 98 static void serial_update_irq(SerialState *s)
97 { 99 {
98 if ((s->lsr & UART_LSR_DR) && (s->ier & UART_IER_RDI)) { 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,11 +163,18 @@ static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val)
161 s->lsr &= ~UART_LSR_THRE; 163 s->lsr &= ~UART_LSR_THRE;
162 serial_update_irq(s); 164 serial_update_irq(s);
163 ch = val; 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 s->thr_ipending = 1; 170 s->thr_ipending = 1;
166 s->lsr |= UART_LSR_THRE; 171 s->lsr |= UART_LSR_THRE;
167 s->lsr |= UART_LSR_TEMT; 172 s->lsr |= UART_LSR_TEMT;
168 serial_update_irq(s); 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 break; 179 break;
171 case 1: 180 case 1:
@@ -223,7 +232,10 @@ static uint32_t serial_ioport_read(void *opaque, uint32_t addr) @@ -223,7 +232,10 @@ static uint32_t serial_ioport_read(void *opaque, uint32_t addr)
223 ret = s->rbr; 232 ret = s->rbr;
224 s->lsr &= ~(UART_LSR_DR | UART_LSR_BI); 233 s->lsr &= ~(UART_LSR_DR | UART_LSR_BI);
225 serial_update_irq(s); 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 break; 240 break;
229 case 1: 241 case 1:
@@ -346,6 +358,25 @@ static int serial_load(QEMUFile *f, void *opaque, int version_id) @@ -346,6 +358,25 @@ static int serial_load(QEMUFile *f, void *opaque, int version_id)
346 return 0; 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 /* If fd is zero, it means that the serial device uses the console */ 380 /* If fd is zero, it means that the serial device uses the console */
350 SerialState *serial_init(int base, qemu_irq irq, CharDriverState *chr) 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,9 +386,9 @@ SerialState *serial_init(int base, qemu_irq irq, CharDriverState *chr)
355 if (!s) 386 if (!s)
356 return NULL; 387 return NULL;
357 s->irq = irq; 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 register_savevm("serial", base, 2, serial_save, serial_load, s); 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,12 +483,12 @@ SerialState *serial_mm_init (target_phys_addr_t base, int it_shift,
452 if (!s) 483 if (!s)
453 return NULL; 484 return NULL;
454 s->irq = irq; 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 s->base = base; 486 s->base = base;
459 s->it_shift = it_shift; 487 s->it_shift = it_shift;
460 488
  489 + qemu_register_reset(serial_reset, s);
  490 + serial_reset(s);
  491 +
461 register_savevm("serial", base, 2, serial_save, serial_load, s); 492 register_savevm("serial", base, 2, serial_save, serial_load, s);
462 493
463 if (ioregister) { 494 if (ioregister) {