⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serial.c

📁 xen 3.2.2 源码
💻 C
📖 第 1 页 / 共 2 页
字号:
    if ( !(s->lsr & UART_LSR_THRE) )        qemu_mod_timer(s->transmit_timer, s->last_xmit_ts + s->char_transmit_time );    if ( s->lsr & UART_LSR_THRE ) {        s->lsr |= UART_LSR_TEMT;        s->thr_ipending = 1;        serial_update_irq(s);    }}static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val){    SerialState *s = opaque;        addr &= 7;#ifdef DEBUG_SERIAL    printf("serial: write addr=0x%02x val=0x%02x\n", addr, val);#endif    switch(addr) {    default:    case 0:        if (s->lcr & UART_LCR_DLAB) {            s->divider = (s->divider & 0xff00) | val;            serial_update_parameters(s);        } else {            s->thr = (uint8_t) val;            if(s->fcr & UART_FCR_FE) {                  fifo_put(s, XMIT_FIFO, s->thr);                  s->thr_ipending = 0;                  s->lsr &= ~UART_LSR_TEMT;                  s->lsr &= ~UART_LSR_THRE;                  serial_update_irq(s);            } else {                  s->thr_ipending = 0;                  s->lsr &= ~UART_LSR_THRE;                  serial_update_irq(s);            }            serial_xmit(s);        }        break;    case 1:        if (s->lcr & UART_LCR_DLAB) {            s->divider = (s->divider & 0x00ff) | (val << 8);            serial_update_parameters(s);        } else {            s->ier = val & 0x0f;            /* If the backend device is a real serial port, turn polling of the modem               status lines on physical port on or off depending on UART_IER_MSI state */            if ( s->poll_msl >= 0 ) {                 if ( s->ier & UART_IER_MSI ) {                     s->poll_msl = 1;                     serial_update_msl(s);                } else {                     qemu_del_timer(s->modem_status_poll);                     s->poll_msl = 0;                }            }            if (s->lsr & UART_LSR_THRE) {                s->thr_ipending = 1;                serial_update_irq(s);            }        }        break;    case 2:        val = val & 0xFF;        if ( s->fcr == val)            break;        /* Did the enable/disable flag change? If so, make sure FIFOs get flushed */        if ( (val ^ s->fcr) & UART_FCR_FE )            val |= UART_FCR_XFR | UART_FCR_RFR;        /* FIFO clear */        if ( val & UART_FCR_RFR ) {            qemu_del_timer(s->fifo_timeout_timer);            s->timeout_ipending=0;            fifo_clear(s,RECV_FIFO);        }                    if ( val & UART_FCR_XFR ) {            fifo_clear(s,XMIT_FIFO);        }                if ( val & UART_FCR_FE ) {            s->iir |= UART_IIR_FE;            /* Set RECV_FIFO trigger Level */            switch ( val & 0xC0 ) {            case UART_FCR_ITL_1:                 s->recv_fifo.itl = 1;                break;            case UART_FCR_ITL_2:                s->recv_fifo.itl = 4;                break;            case UART_FCR_ITL_3:                s->recv_fifo.itl = 8;                break;            case UART_FCR_ITL_4:                s->recv_fifo.itl = 14;                break;            }        } else            s->iir &= ~UART_IIR_FE;        /* Set fcr - or at least the bits in it that are supposed to "stick" */        s->fcr = val & 0xC9;        serial_update_irq(s);        break;    case 3:        {            int break_enable;            s->lcr = val;            serial_update_parameters(s);            break_enable = (val >> 6) & 1;            if (break_enable != s->last_break_enable) {                s->last_break_enable = break_enable;                qemu_chr_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_BREAK,                                &break_enable);            }        }        break;    case 4:	{            int flags;	    int old_mcr = s->mcr;            s->mcr = val & 0x1f;            if ( val & UART_MCR_LOOP )                break;            if ( s->poll_msl >= 0 && old_mcr != s->mcr ) {                qemu_chr_ioctl(s->chr,CHR_IOCTL_SERIAL_GET_TIOCM, &flags);                flags &= ~( TIOCM_RTS | TIOCM_DTR );                if ( val & UART_MCR_RTS )                    flags |= TIOCM_RTS;                if ( val & UART_MCR_DTR )                    flags |= TIOCM_DTR;                qemu_chr_ioctl(s->chr,CHR_IOCTL_SERIAL_SET_TIOCM, &flags);                /* Update the modem status after a one-character-send wait-time, since there may be a response                   from the device/computer at the other end of the serial line */                qemu_mod_timer(s->modem_status_poll, qemu_get_clock(vm_clock) + s->char_transmit_time );            }	}        break;    case 5:        break;    case 6:        break;    case 7:        s->scr = val;        break;    }}static uint32_t serial_ioport_read(void *opaque, uint32_t addr){    SerialState *s = opaque;    uint32_t ret;    addr &= 7;    switch(addr) {    default:    case 0:        if (s->lcr & UART_LCR_DLAB) {            ret = s->divider & 0xff;         } else {            if(s->fcr & UART_FCR_FE) {                ret = fifo_get(s,RECV_FIFO);                if ( s->recv_fifo.count == 0 )                    s->lsr &= ~(UART_LSR_DR | UART_LSR_BI);                else                    qemu_mod_timer(s->fifo_timeout_timer, qemu_get_clock (vm_clock) + s->char_transmit_time * 4 );                s->timeout_ipending = 0;           } else {               ret = s->rbr;               s->lsr &= ~(UART_LSR_DR | UART_LSR_BI);           }           serial_update_irq(s);        }        break;    case 1:        if (s->lcr & UART_LCR_DLAB) {            ret = (s->divider >> 8) & 0xff;        } else {            ret = s->ier;        }        break;    case 2:        ret = s->iir;        s->thr_ipending = 0;        serial_update_irq(s);        break;    case 3:        ret = s->lcr;        break;    case 4:        ret = s->mcr;        break;    case 5:	serial_get_token();        ret = s->lsr;        /* Clear break interrupt */        if ( s->lsr & UART_LSR_BI ) {            s->lsr &= ~UART_LSR_BI;            serial_update_irq(s);        }        break;    case 6:	serial_get_token();        if (s->mcr & UART_MCR_LOOP) {            /* in loopback, the modem output pins are connected to the               inputs */            ret = (s->mcr & 0x0c) << 4;            ret |= (s->mcr & 0x02) << 3;            ret |= (s->mcr & 0x01) << 5;        } else {            if ( s->poll_msl >= 0 )                serial_update_msl(s);            ret = s->msr;            /* Clear delta bits & msr int after read, if they were set */            if ( s->msr & UART_MSR_ANY_DELTA ) {                s->msr &= 0xF0;                serial_update_irq(s);            }        }        break;    case 7:        ret = s->scr;        break;    }#ifdef DEBUG_SERIAL    printf("serial: read addr=0x%02x val=0x%02x\n", addr, ret);#endif    return ret;}static int serial_can_receive(SerialState *s){    if(s->fcr & UART_FCR_FE) {        if(s->recv_fifo.count < UART_FIFO_LENGTH)        /* Advertise (fifo.itl - fifo.count) bytes when count < ITL, and 1 if above. If UART_FIFO_LENGTH - fifo.count is        advertised the effect will be to almost always fill the fifo completely before the guest has a chance to respond,        effectively overriding the ITL that the guest has set. */             return ( s->recv_fifo.count <= s->recv_fifo.itl ) ? s->recv_fifo.itl - s->recv_fifo.count : 1;        else             return 0;    } else {        return !(s->lsr & UART_LSR_DR);    }}static void serial_receive_break(SerialState *s){    s->rbr = 0;    s->lsr |= UART_LSR_BI | UART_LSR_DR;    serial_update_irq(s);} /* There's data in recv_fifo and s->rbr has not been read for 4 char transmit times */static void fifo_timeout_int (void *opaque) {    SerialState *s = opaque;    if ( s->recv_fifo.count ) {        s->timeout_ipending = 1;        serial_update_irq(s);    }}static int serial_can_receive1(void *opaque){    SerialState *s = opaque;    return serial_can_receive(s);}static void serial_receive1(void *opaque, const uint8_t *buf, int size){    SerialState *s = opaque;    tokens_avail = TOKENS_MAX;    if(s->fcr & UART_FCR_FE) {        int i;        for (i = 0; i < size; i++) {            fifo_put(s, RECV_FIFO, buf[i]);        }        s->lsr |= UART_LSR_DR;        /* call the timeout receive callback in 4 char transmit time */        qemu_mod_timer(s->fifo_timeout_timer, qemu_get_clock (vm_clock) + s->char_transmit_time * 4);    } else {        s->rbr = buf[0];        s->lsr |= UART_LSR_DR;    }    serial_update_irq(s);}static void serial_event(void *opaque, int event){    SerialState *s = opaque;    tokens_avail = TOKENS_MAX;    if (event == CHR_EVENT_BREAK)        serial_receive_break(s);}static void serial_save(QEMUFile *f, void *opaque){    SerialState *s = opaque;    qemu_put_be16s(f,&s->divider);    qemu_put_8s(f,&s->rbr);    qemu_put_8s(f,&s->ier);    qemu_put_8s(f,&s->iir);    qemu_put_8s(f,&s->lcr);    qemu_put_8s(f,&s->mcr);    qemu_put_8s(f,&s->lsr);    qemu_put_8s(f,&s->msr);    qemu_put_8s(f,&s->scr);    qemu_get_8s(f,&s->fcr);}static int serial_load(QEMUFile *f, void *opaque, int version_id){    SerialState *s = opaque;    if(version_id > 2)        return -EINVAL;    if (version_id >= 2)        qemu_get_be16s(f, &s->divider);    else        s->divider = qemu_get_byte(f);    qemu_get_8s(f,&s->rbr);    qemu_get_8s(f,&s->ier);    qemu_get_8s(f,&s->iir);    qemu_get_8s(f,&s->lcr);    qemu_get_8s(f,&s->mcr);    qemu_get_8s(f,&s->lsr);    qemu_get_8s(f,&s->msr);    qemu_get_8s(f,&s->scr);    qemu_get_8s(f,&s->fcr);    return 0;}/* If fd is zero, it means that the serial device uses the console */SerialState *serial_init(SetIRQFunc *set_irq, void *opaque,                         int base, int irq, CharDriverState *chr){    SerialState *s;    s = qemu_mallocz(sizeof(SerialState));    if (!s)        return NULL;    s->set_irq = set_irq;    s->irq_opaque = opaque;    s->irq = irq;    s->ier = 0;    s->lsr = UART_LSR_TEMT | UART_LSR_THRE;    s->iir = UART_IIR_NO_INT;    s->mcr = UART_MCR_OUT2;    s->msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS;    /* Default to 9600 baud, no parity, one stop bit */    s->divider = 0x0C;    s->tsr_retry = 0;    s->char_transmit_time = ( ticks_per_sec / 9600 ) * 9;    s->modem_status_poll = qemu_new_timer(vm_clock, ( QEMUTimerCB *) serial_update_msl, s);      s->poll_msl = 0;    fifo_clear(s,RECV_FIFO);    fifo_clear(s,XMIT_FIFO);    s->last_xmit_ts = qemu_get_clock(vm_clock);    s->fifo_timeout_timer = qemu_new_timer(vm_clock, ( QEMUTimerCB *) fifo_timeout_int, s);    s->transmit_timer = qemu_new_timer(vm_clock, ( QEMUTimerCB *) serial_xmit, s);    register_savevm("serial", base, 2, serial_save, serial_load, s);    register_ioport_write(base, 8, 1, serial_ioport_write, s);    register_ioport_read(base, 8, 1, serial_ioport_read, s);    s->chr = chr;    qemu_chr_add_handlers(chr, serial_can_receive1, serial_receive1,                           serial_event, s);    serial_update_msl(s);    return s;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -