Add serial loopback mode (patch from Hervé Poussineau).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3973 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
		
							parent
							
								
									e41c0f263f
								
							
						
					
					
						commit
						b2a5160c9f
					
				
							
								
								
									
										47
									
								
								hw/serial.c
								
								
								
								
							
							
						
						
									
										47
									
								
								hw/serial.c
								
								
								
								
							| 
						 | 
					@ -93,6 +93,8 @@ struct SerialState {
 | 
				
			||||||
    int it_shift;
 | 
					    int it_shift;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void serial_receive_byte(SerialState *s, int ch);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void serial_update_irq(SerialState *s)
 | 
					static void serial_update_irq(SerialState *s)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if ((s->lsr & UART_LSR_DR) && (s->ier & UART_IER_RDI)) {
 | 
					    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)
 | 
				
			||||||
            s->lsr &= ~UART_LSR_THRE;
 | 
					            s->lsr &= ~UART_LSR_THRE;
 | 
				
			||||||
            serial_update_irq(s);
 | 
					            serial_update_irq(s);
 | 
				
			||||||
            ch = val;
 | 
					            ch = val;
 | 
				
			||||||
            qemu_chr_write(s->chr, &ch, 1);
 | 
					            if (!(s->mcr & UART_MCR_LOOP)) {
 | 
				
			||||||
 | 
					                /* when not in loopback mode, send the char */
 | 
				
			||||||
 | 
					                qemu_chr_write(s->chr, &ch, 1);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            s->thr_ipending = 1;
 | 
					            s->thr_ipending = 1;
 | 
				
			||||||
            s->lsr |= UART_LSR_THRE;
 | 
					            s->lsr |= UART_LSR_THRE;
 | 
				
			||||||
            s->lsr |= UART_LSR_TEMT;
 | 
					            s->lsr |= UART_LSR_TEMT;
 | 
				
			||||||
            serial_update_irq(s);
 | 
					            serial_update_irq(s);
 | 
				
			||||||
 | 
					            if (s->mcr & UART_MCR_LOOP) {
 | 
				
			||||||
 | 
					                /* in loopback mode, say that we just received a char */
 | 
				
			||||||
 | 
					                serial_receive_byte(s, ch);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 1:
 | 
					    case 1:
 | 
				
			||||||
| 
						 | 
					@ -223,7 +232,10 @@ static uint32_t serial_ioport_read(void *opaque, uint32_t addr)
 | 
				
			||||||
            ret = s->rbr;
 | 
					            ret = s->rbr;
 | 
				
			||||||
            s->lsr &= ~(UART_LSR_DR | UART_LSR_BI);
 | 
					            s->lsr &= ~(UART_LSR_DR | UART_LSR_BI);
 | 
				
			||||||
            serial_update_irq(s);
 | 
					            serial_update_irq(s);
 | 
				
			||||||
            qemu_chr_accept_input(s->chr);
 | 
					            if (!(s->mcr & UART_MCR_LOOP)) {
 | 
				
			||||||
 | 
					                /* in loopback mode, don't receive any data */
 | 
				
			||||||
 | 
					                qemu_chr_accept_input(s->chr);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 1:
 | 
					    case 1:
 | 
				
			||||||
| 
						 | 
					@ -346,6 +358,25 @@ static int serial_load(QEMUFile *f, void *opaque, int version_id)
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void serial_reset(void *opaque)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    SerialState *s = opaque;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    s->divider = 0;
 | 
				
			||||||
 | 
					    s->rbr = 0;
 | 
				
			||||||
 | 
					    s->ier = 0;
 | 
				
			||||||
 | 
					    s->iir = UART_IIR_NO_INT;
 | 
				
			||||||
 | 
					    s->lcr = 0;
 | 
				
			||||||
 | 
					    s->mcr = 0;
 | 
				
			||||||
 | 
					    s->lsr = UART_LSR_TEMT | UART_LSR_THRE;
 | 
				
			||||||
 | 
					    s->msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS;
 | 
				
			||||||
 | 
					    s->scr = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    s->thr_ipending = 0;
 | 
				
			||||||
 | 
					    s->last_break_enable = 0;
 | 
				
			||||||
 | 
					    qemu_irq_lower(s->irq);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* If fd is zero, it means that the serial device uses the console */
 | 
					/* If fd is zero, it means that the serial device uses the console */
 | 
				
			||||||
SerialState *serial_init(int base, qemu_irq irq, CharDriverState *chr)
 | 
					SerialState *serial_init(int base, qemu_irq irq, CharDriverState *chr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -355,9 +386,9 @@ SerialState *serial_init(int base, qemu_irq irq, CharDriverState *chr)
 | 
				
			||||||
    if (!s)
 | 
					    if (!s)
 | 
				
			||||||
        return NULL;
 | 
					        return NULL;
 | 
				
			||||||
    s->irq = irq;
 | 
					    s->irq = irq;
 | 
				
			||||||
    s->lsr = UART_LSR_TEMT | UART_LSR_THRE;
 | 
					
 | 
				
			||||||
    s->iir = UART_IIR_NO_INT;
 | 
					    qemu_register_reset(serial_reset, s);
 | 
				
			||||||
    s->msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS;
 | 
					    serial_reset(s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    register_savevm("serial", base, 2, serial_save, serial_load, s);
 | 
					    register_savevm("serial", base, 2, serial_save, serial_load, s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -452,12 +483,12 @@ SerialState *serial_mm_init (target_phys_addr_t base, int it_shift,
 | 
				
			||||||
    if (!s)
 | 
					    if (!s)
 | 
				
			||||||
        return NULL;
 | 
					        return NULL;
 | 
				
			||||||
    s->irq = irq;
 | 
					    s->irq = irq;
 | 
				
			||||||
    s->lsr = UART_LSR_TEMT | UART_LSR_THRE;
 | 
					 | 
				
			||||||
    s->iir = UART_IIR_NO_INT;
 | 
					 | 
				
			||||||
    s->msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS;
 | 
					 | 
				
			||||||
    s->base = base;
 | 
					    s->base = base;
 | 
				
			||||||
    s->it_shift = it_shift;
 | 
					    s->it_shift = it_shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qemu_register_reset(serial_reset, s);
 | 
				
			||||||
 | 
					    serial_reset(s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    register_savevm("serial", base, 2, serial_save, serial_load, s);
 | 
					    register_savevm("serial", base, 2, serial_save, serial_load, s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (ioregister) {
 | 
					    if (ioregister) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue