Statistics
| Branch: | Revision:

root / hw / serial.c @ b072a3c8

History | View | Annotate | Download (27.4 kB)

1 80cabfad bellard
/*
2 81174dae aliguori
 * QEMU 16550A UART emulation
3 5fafdf24 ths
 *
4 80cabfad bellard
 * Copyright (c) 2003-2004 Fabrice Bellard
5 81174dae aliguori
 * Copyright (c) 2008 Citrix Systems, Inc.
6 5fafdf24 ths
 *
7 80cabfad bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 80cabfad bellard
 * of this software and associated documentation files (the "Software"), to deal
9 80cabfad bellard
 * in the Software without restriction, including without limitation the rights
10 80cabfad bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 80cabfad bellard
 * copies of the Software, and to permit persons to whom the Software is
12 80cabfad bellard
 * furnished to do so, subject to the following conditions:
13 80cabfad bellard
 *
14 80cabfad bellard
 * The above copyright notice and this permission notice shall be included in
15 80cabfad bellard
 * all copies or substantial portions of the Software.
16 80cabfad bellard
 *
17 80cabfad bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 80cabfad bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 80cabfad bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 80cabfad bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 80cabfad bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 80cabfad bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 80cabfad bellard
 * THE SOFTWARE.
24 80cabfad bellard
 */
25 87ecb68b pbrook
#include "hw.h"
26 87ecb68b pbrook
#include "qemu-char.h"
27 87ecb68b pbrook
#include "isa.h"
28 87ecb68b pbrook
#include "pc.h"
29 6936bfe5 aurel32
#include "qemu-timer.h"
30 666daa68 Markus Armbruster
#include "sysemu.h"
31 80cabfad bellard
32 80cabfad bellard
//#define DEBUG_SERIAL
33 80cabfad bellard
34 80cabfad bellard
#define UART_LCR_DLAB        0x80        /* Divisor latch access bit */
35 80cabfad bellard
36 80cabfad bellard
#define UART_IER_MSI        0x08        /* Enable Modem status interrupt */
37 80cabfad bellard
#define UART_IER_RLSI        0x04        /* Enable receiver line status interrupt */
38 80cabfad bellard
#define UART_IER_THRI        0x02        /* Enable Transmitter holding register int. */
39 80cabfad bellard
#define UART_IER_RDI        0x01        /* Enable receiver data interrupt */
40 80cabfad bellard
41 80cabfad bellard
#define UART_IIR_NO_INT        0x01        /* No interrupts pending */
42 80cabfad bellard
#define UART_IIR_ID        0x06        /* Mask for the interrupt ID */
43 80cabfad bellard
44 80cabfad bellard
#define UART_IIR_MSI        0x00        /* Modem status interrupt */
45 80cabfad bellard
#define UART_IIR_THRI        0x02        /* Transmitter holding register empty */
46 80cabfad bellard
#define UART_IIR_RDI        0x04        /* Receiver data interrupt */
47 80cabfad bellard
#define UART_IIR_RLSI        0x06        /* Receiver line status interrupt */
48 81174dae aliguori
#define UART_IIR_CTI    0x0C    /* Character Timeout Indication */
49 81174dae aliguori
50 81174dae aliguori
#define UART_IIR_FENF   0x80    /* Fifo enabled, but not functionning */
51 81174dae aliguori
#define UART_IIR_FE     0xC0    /* Fifo enabled */
52 80cabfad bellard
53 80cabfad bellard
/*
54 80cabfad bellard
 * These are the definitions for the Modem Control Register
55 80cabfad bellard
 */
56 80cabfad bellard
#define UART_MCR_LOOP        0x10        /* Enable loopback test mode */
57 80cabfad bellard
#define UART_MCR_OUT2        0x08        /* Out2 complement */
58 80cabfad bellard
#define UART_MCR_OUT1        0x04        /* Out1 complement */
59 80cabfad bellard
#define UART_MCR_RTS        0x02        /* RTS complement */
60 80cabfad bellard
#define UART_MCR_DTR        0x01        /* DTR complement */
61 80cabfad bellard
62 80cabfad bellard
/*
63 80cabfad bellard
 * These are the definitions for the Modem Status Register
64 80cabfad bellard
 */
65 80cabfad bellard
#define UART_MSR_DCD        0x80        /* Data Carrier Detect */
66 80cabfad bellard
#define UART_MSR_RI        0x40        /* Ring Indicator */
67 80cabfad bellard
#define UART_MSR_DSR        0x20        /* Data Set Ready */
68 80cabfad bellard
#define UART_MSR_CTS        0x10        /* Clear to Send */
69 80cabfad bellard
#define UART_MSR_DDCD        0x08        /* Delta DCD */
70 80cabfad bellard
#define UART_MSR_TERI        0x04        /* Trailing edge ring indicator */
71 80cabfad bellard
#define UART_MSR_DDSR        0x02        /* Delta DSR */
72 80cabfad bellard
#define UART_MSR_DCTS        0x01        /* Delta CTS */
73 80cabfad bellard
#define UART_MSR_ANY_DELTA 0x0F        /* Any of the delta bits! */
74 80cabfad bellard
75 80cabfad bellard
#define UART_LSR_TEMT        0x40        /* Transmitter empty */
76 80cabfad bellard
#define UART_LSR_THRE        0x20        /* Transmit-hold-register empty */
77 80cabfad bellard
#define UART_LSR_BI        0x10        /* Break interrupt indicator */
78 80cabfad bellard
#define UART_LSR_FE        0x08        /* Frame error indicator */
79 80cabfad bellard
#define UART_LSR_PE        0x04        /* Parity error indicator */
80 80cabfad bellard
#define UART_LSR_OE        0x02        /* Overrun error indicator */
81 80cabfad bellard
#define UART_LSR_DR        0x01        /* Receiver data ready */
82 81174dae aliguori
#define UART_LSR_INT_ANY 0x1E        /* Any of the lsr-interrupt-triggering status bits */
83 80cabfad bellard
84 81174dae aliguori
/* Interrupt trigger levels. The byte-counts are for 16550A - in newer UARTs the byte-count for each ITL is higher. */
85 81174dae aliguori
86 81174dae aliguori
#define UART_FCR_ITL_1      0x00 /* 1 byte ITL */
87 81174dae aliguori
#define UART_FCR_ITL_2      0x40 /* 4 bytes ITL */
88 81174dae aliguori
#define UART_FCR_ITL_3      0x80 /* 8 bytes ITL */
89 81174dae aliguori
#define UART_FCR_ITL_4      0xC0 /* 14 bytes ITL */
90 81174dae aliguori
91 81174dae aliguori
#define UART_FCR_DMS        0x08    /* DMA Mode Select */
92 81174dae aliguori
#define UART_FCR_XFR        0x04    /* XMIT Fifo Reset */
93 81174dae aliguori
#define UART_FCR_RFR        0x02    /* RCVR Fifo Reset */
94 81174dae aliguori
#define UART_FCR_FE         0x01    /* FIFO Enable */
95 81174dae aliguori
96 81174dae aliguori
#define UART_FIFO_LENGTH    16      /* 16550A Fifo Length */
97 81174dae aliguori
98 81174dae aliguori
#define XMIT_FIFO           0
99 81174dae aliguori
#define RECV_FIFO           1
100 81174dae aliguori
#define MAX_XMIT_RETRY      4
101 81174dae aliguori
102 b6601141 Michal Novotny
#ifdef DEBUG_SERIAL
103 b6601141 Michal Novotny
#define DPRINTF(fmt, ...) \
104 46411f86 Stefan Weil
do { fprintf(stderr, "serial: " fmt , ## __VA_ARGS__); } while (0)
105 b6601141 Michal Novotny
#else
106 b6601141 Michal Novotny
#define DPRINTF(fmt, ...) \
107 46411f86 Stefan Weil
do {} while (0)
108 b6601141 Michal Novotny
#endif
109 b6601141 Michal Novotny
110 2b321d69 Juan Quintela
typedef struct SerialFIFO {
111 81174dae aliguori
    uint8_t data[UART_FIFO_LENGTH];
112 81174dae aliguori
    uint8_t count;
113 81174dae aliguori
    uint8_t itl;                        /* Interrupt Trigger Level */
114 81174dae aliguori
    uint8_t tail;
115 81174dae aliguori
    uint8_t head;
116 2b321d69 Juan Quintela
} SerialFIFO;
117 6936bfe5 aurel32
118 b41a2cd1 bellard
struct SerialState {
119 508d92d0 bellard
    uint16_t divider;
120 80cabfad bellard
    uint8_t rbr; /* receive register */
121 81174dae aliguori
    uint8_t thr; /* transmit holding register */
122 81174dae aliguori
    uint8_t tsr; /* transmit shift register */
123 80cabfad bellard
    uint8_t ier;
124 80cabfad bellard
    uint8_t iir; /* read only */
125 80cabfad bellard
    uint8_t lcr;
126 80cabfad bellard
    uint8_t mcr;
127 80cabfad bellard
    uint8_t lsr; /* read only */
128 3e749fe1 bellard
    uint8_t msr; /* read only */
129 80cabfad bellard
    uint8_t scr;
130 81174dae aliguori
    uint8_t fcr;
131 747791f1 Juan Quintela
    uint8_t fcr_vmstate; /* we can't write directly this value
132 747791f1 Juan Quintela
                            it has side effects */
133 80cabfad bellard
    /* NOTE: this hidden state is necessary for tx irq generation as
134 80cabfad bellard
       it can be reset while reading iir */
135 80cabfad bellard
    int thr_ipending;
136 d537cf6c pbrook
    qemu_irq irq;
137 82c643ff bellard
    CharDriverState *chr;
138 f8d179e3 bellard
    int last_break_enable;
139 e5d13e2f bellard
    int it_shift;
140 b6cd0ea1 aurel32
    int baudbase;
141 81174dae aliguori
    int tsr_retry;
142 9826fd59 Gerd Hoffmann
    uint32_t wakeup;
143 81174dae aliguori
144 81174dae aliguori
    uint64_t last_xmit_ts;              /* Time when the last byte was successfully sent out of the tsr */
145 81174dae aliguori
    SerialFIFO recv_fifo;
146 81174dae aliguori
    SerialFIFO xmit_fifo;
147 81174dae aliguori
148 81174dae aliguori
    struct QEMUTimer *fifo_timeout_timer;
149 81174dae aliguori
    int timeout_ipending;                   /* timeout interrupt pending state */
150 81174dae aliguori
    struct QEMUTimer *transmit_timer;
151 81174dae aliguori
152 81174dae aliguori
153 81174dae aliguori
    uint64_t char_transmit_time;               /* time to transmit a char in ticks*/
154 81174dae aliguori
    int poll_msl;
155 81174dae aliguori
156 81174dae aliguori
    struct QEMUTimer *modem_status_poll;
157 8e8ffc44 Richard Henderson
    MemoryRegion io;
158 b41a2cd1 bellard
};
159 80cabfad bellard
160 ac0be998 Gerd Hoffmann
typedef struct ISASerialState {
161 ac0be998 Gerd Hoffmann
    ISADevice dev;
162 e8ee28fb Gerd Hoffmann
    uint32_t index;
163 ac0be998 Gerd Hoffmann
    uint32_t iobase;
164 ac0be998 Gerd Hoffmann
    uint32_t isairq;
165 ac0be998 Gerd Hoffmann
    SerialState state;
166 ac0be998 Gerd Hoffmann
} ISASerialState;
167 ac0be998 Gerd Hoffmann
168 81174dae aliguori
static void serial_receive1(void *opaque, const uint8_t *buf, int size);
169 b2a5160c balrog
170 81174dae aliguori
static void fifo_clear(SerialState *s, int fifo)
171 80cabfad bellard
{
172 81174dae aliguori
    SerialFIFO *f = (fifo) ? &s->recv_fifo : &s->xmit_fifo;
173 81174dae aliguori
    memset(f->data, 0, UART_FIFO_LENGTH);
174 81174dae aliguori
    f->count = 0;
175 81174dae aliguori
    f->head = 0;
176 81174dae aliguori
    f->tail = 0;
177 80cabfad bellard
}
178 80cabfad bellard
179 81174dae aliguori
static int fifo_put(SerialState *s, int fifo, uint8_t chr)
180 6936bfe5 aurel32
{
181 81174dae aliguori
    SerialFIFO *f = (fifo) ? &s->recv_fifo : &s->xmit_fifo;
182 6936bfe5 aurel32
183 71e605f8 Justin T. Gibbs
    /* Receive overruns do not overwrite FIFO contents. */
184 71e605f8 Justin T. Gibbs
    if (fifo == XMIT_FIFO || f->count < UART_FIFO_LENGTH) {
185 6936bfe5 aurel32
186 71e605f8 Justin T. Gibbs
        f->data[f->head++] = chr;
187 71e605f8 Justin T. Gibbs
188 71e605f8 Justin T. Gibbs
        if (f->head == UART_FIFO_LENGTH)
189 71e605f8 Justin T. Gibbs
            f->head = 0;
190 71e605f8 Justin T. Gibbs
    }
191 71e605f8 Justin T. Gibbs
192 71e605f8 Justin T. Gibbs
    if (f->count < UART_FIFO_LENGTH)
193 71e605f8 Justin T. Gibbs
        f->count++;
194 71e605f8 Justin T. Gibbs
    else if (fifo == RECV_FIFO)
195 71e605f8 Justin T. Gibbs
        s->lsr |= UART_LSR_OE;
196 81174dae aliguori
197 81174dae aliguori
    return 1;
198 81174dae aliguori
}
199 81174dae aliguori
200 81174dae aliguori
static uint8_t fifo_get(SerialState *s, int fifo)
201 81174dae aliguori
{
202 81174dae aliguori
    SerialFIFO *f = (fifo) ? &s->recv_fifo : &s->xmit_fifo;
203 81174dae aliguori
    uint8_t c;
204 81174dae aliguori
205 81174dae aliguori
    if(f->count == 0)
206 81174dae aliguori
        return 0;
207 81174dae aliguori
208 81174dae aliguori
    c = f->data[f->tail++];
209 81174dae aliguori
    if (f->tail == UART_FIFO_LENGTH)
210 81174dae aliguori
        f->tail = 0;
211 81174dae aliguori
    f->count--;
212 81174dae aliguori
213 81174dae aliguori
    return c;
214 81174dae aliguori
}
215 6936bfe5 aurel32
216 81174dae aliguori
static void serial_update_irq(SerialState *s)
217 81174dae aliguori
{
218 81174dae aliguori
    uint8_t tmp_iir = UART_IIR_NO_INT;
219 81174dae aliguori
220 81174dae aliguori
    if ((s->ier & UART_IER_RLSI) && (s->lsr & UART_LSR_INT_ANY)) {
221 81174dae aliguori
        tmp_iir = UART_IIR_RLSI;
222 5628a626 balrog
    } else if ((s->ier & UART_IER_RDI) && s->timeout_ipending) {
223 c9a33054 balrog
        /* Note that(s->ier & UART_IER_RDI) can mask this interrupt,
224 c9a33054 balrog
         * this is not in the specification but is observed on existing
225 c9a33054 balrog
         * hardware.  */
226 81174dae aliguori
        tmp_iir = UART_IIR_CTI;
227 2d6ee8e7 Juergen Lock
    } else if ((s->ier & UART_IER_RDI) && (s->lsr & UART_LSR_DR) &&
228 2d6ee8e7 Juergen Lock
               (!(s->fcr & UART_FCR_FE) ||
229 2d6ee8e7 Juergen Lock
                s->recv_fifo.count >= s->recv_fifo.itl)) {
230 2d6ee8e7 Juergen Lock
        tmp_iir = UART_IIR_RDI;
231 81174dae aliguori
    } else if ((s->ier & UART_IER_THRI) && s->thr_ipending) {
232 81174dae aliguori
        tmp_iir = UART_IIR_THRI;
233 81174dae aliguori
    } else if ((s->ier & UART_IER_MSI) && (s->msr & UART_MSR_ANY_DELTA)) {
234 81174dae aliguori
        tmp_iir = UART_IIR_MSI;
235 81174dae aliguori
    }
236 81174dae aliguori
237 81174dae aliguori
    s->iir = tmp_iir | (s->iir & 0xF0);
238 81174dae aliguori
239 81174dae aliguori
    if (tmp_iir != UART_IIR_NO_INT) {
240 81174dae aliguori
        qemu_irq_raise(s->irq);
241 81174dae aliguori
    } else {
242 81174dae aliguori
        qemu_irq_lower(s->irq);
243 6936bfe5 aurel32
    }
244 6936bfe5 aurel32
}
245 6936bfe5 aurel32
246 f8d179e3 bellard
static void serial_update_parameters(SerialState *s)
247 f8d179e3 bellard
{
248 81174dae aliguori
    int speed, parity, data_bits, stop_bits, frame_size;
249 2122c51a bellard
    QEMUSerialSetParams ssp;
250 f8d179e3 bellard
251 81174dae aliguori
    if (s->divider == 0)
252 81174dae aliguori
        return;
253 81174dae aliguori
254 718b8aec Stefan Weil
    /* Start bit. */
255 81174dae aliguori
    frame_size = 1;
256 f8d179e3 bellard
    if (s->lcr & 0x08) {
257 718b8aec Stefan Weil
        /* Parity bit. */
258 718b8aec Stefan Weil
        frame_size++;
259 f8d179e3 bellard
        if (s->lcr & 0x10)
260 f8d179e3 bellard
            parity = 'E';
261 f8d179e3 bellard
        else
262 f8d179e3 bellard
            parity = 'O';
263 f8d179e3 bellard
    } else {
264 f8d179e3 bellard
            parity = 'N';
265 f8d179e3 bellard
    }
266 5fafdf24 ths
    if (s->lcr & 0x04)
267 f8d179e3 bellard
        stop_bits = 2;
268 f8d179e3 bellard
    else
269 f8d179e3 bellard
        stop_bits = 1;
270 81174dae aliguori
271 f8d179e3 bellard
    data_bits = (s->lcr & 0x03) + 5;
272 81174dae aliguori
    frame_size += data_bits + stop_bits;
273 b6cd0ea1 aurel32
    speed = s->baudbase / s->divider;
274 2122c51a bellard
    ssp.speed = speed;
275 2122c51a bellard
    ssp.parity = parity;
276 2122c51a bellard
    ssp.data_bits = data_bits;
277 2122c51a bellard
    ssp.stop_bits = stop_bits;
278 6ee093c9 Juan Quintela
    s->char_transmit_time =  (get_ticks_per_sec() / speed) * frame_size;
279 41084f1b Anthony Liguori
    qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
280 b6601141 Michal Novotny
281 b6601141 Michal Novotny
    DPRINTF("speed=%d parity=%c data=%d stop=%d\n",
282 f8d179e3 bellard
           speed, parity, data_bits, stop_bits);
283 f8d179e3 bellard
}
284 f8d179e3 bellard
285 81174dae aliguori
static void serial_update_msl(SerialState *s)
286 81174dae aliguori
{
287 81174dae aliguori
    uint8_t omsr;
288 81174dae aliguori
    int flags;
289 81174dae aliguori
290 81174dae aliguori
    qemu_del_timer(s->modem_status_poll);
291 81174dae aliguori
292 41084f1b Anthony Liguori
    if (qemu_chr_fe_ioctl(s->chr,CHR_IOCTL_SERIAL_GET_TIOCM, &flags) == -ENOTSUP) {
293 81174dae aliguori
        s->poll_msl = -1;
294 81174dae aliguori
        return;
295 81174dae aliguori
    }
296 81174dae aliguori
297 81174dae aliguori
    omsr = s->msr;
298 81174dae aliguori
299 81174dae aliguori
    s->msr = (flags & CHR_TIOCM_CTS) ? s->msr | UART_MSR_CTS : s->msr & ~UART_MSR_CTS;
300 81174dae aliguori
    s->msr = (flags & CHR_TIOCM_DSR) ? s->msr | UART_MSR_DSR : s->msr & ~UART_MSR_DSR;
301 81174dae aliguori
    s->msr = (flags & CHR_TIOCM_CAR) ? s->msr | UART_MSR_DCD : s->msr & ~UART_MSR_DCD;
302 81174dae aliguori
    s->msr = (flags & CHR_TIOCM_RI) ? s->msr | UART_MSR_RI : s->msr & ~UART_MSR_RI;
303 81174dae aliguori
304 81174dae aliguori
    if (s->msr != omsr) {
305 81174dae aliguori
         /* Set delta bits */
306 81174dae aliguori
         s->msr = s->msr | ((s->msr >> 4) ^ (omsr >> 4));
307 81174dae aliguori
         /* UART_MSR_TERI only if change was from 1 -> 0 */
308 81174dae aliguori
         if ((s->msr & UART_MSR_TERI) && !(omsr & UART_MSR_RI))
309 81174dae aliguori
             s->msr &= ~UART_MSR_TERI;
310 81174dae aliguori
         serial_update_irq(s);
311 81174dae aliguori
    }
312 81174dae aliguori
313 81174dae aliguori
    /* The real 16550A apparently has a 250ns response latency to line status changes.
314 81174dae aliguori
       We'll be lazy and poll only every 10ms, and only poll it at all if MSI interrupts are turned on */
315 81174dae aliguori
316 81174dae aliguori
    if (s->poll_msl)
317 74475455 Paolo Bonzini
        qemu_mod_timer(s->modem_status_poll, qemu_get_clock_ns(vm_clock) + get_ticks_per_sec() / 100);
318 81174dae aliguori
}
319 81174dae aliguori
320 81174dae aliguori
static void serial_xmit(void *opaque)
321 81174dae aliguori
{
322 81174dae aliguori
    SerialState *s = opaque;
323 74475455 Paolo Bonzini
    uint64_t new_xmit_ts = qemu_get_clock_ns(vm_clock);
324 81174dae aliguori
325 81174dae aliguori
    if (s->tsr_retry <= 0) {
326 81174dae aliguori
        if (s->fcr & UART_FCR_FE) {
327 81174dae aliguori
            s->tsr = fifo_get(s,XMIT_FIFO);
328 81174dae aliguori
            if (!s->xmit_fifo.count)
329 81174dae aliguori
                s->lsr |= UART_LSR_THRE;
330 81174dae aliguori
        } else {
331 81174dae aliguori
            s->tsr = s->thr;
332 81174dae aliguori
            s->lsr |= UART_LSR_THRE;
333 81174dae aliguori
        }
334 81174dae aliguori
    }
335 81174dae aliguori
336 81174dae aliguori
    if (s->mcr & UART_MCR_LOOP) {
337 81174dae aliguori
        /* in loopback mode, say that we just received a char */
338 81174dae aliguori
        serial_receive1(s, &s->tsr, 1);
339 2cc6e0a1 Anthony Liguori
    } else if (qemu_chr_fe_write(s->chr, &s->tsr, 1) != 1) {
340 81174dae aliguori
        if ((s->tsr_retry > 0) && (s->tsr_retry <= MAX_XMIT_RETRY)) {
341 81174dae aliguori
            s->tsr_retry++;
342 81174dae aliguori
            qemu_mod_timer(s->transmit_timer,  new_xmit_ts + s->char_transmit_time);
343 81174dae aliguori
            return;
344 81174dae aliguori
        } else if (s->poll_msl < 0) {
345 81174dae aliguori
            /* If we exceed MAX_XMIT_RETRY and the backend is not a real serial port, then
346 81174dae aliguori
            drop any further failed writes instantly, until we get one that goes through.
347 81174dae aliguori
            This is to prevent guests that log to unconnected pipes or pty's from stalling. */
348 81174dae aliguori
            s->tsr_retry = -1;
349 81174dae aliguori
        }
350 81174dae aliguori
    }
351 81174dae aliguori
    else {
352 81174dae aliguori
        s->tsr_retry = 0;
353 81174dae aliguori
    }
354 81174dae aliguori
355 74475455 Paolo Bonzini
    s->last_xmit_ts = qemu_get_clock_ns(vm_clock);
356 81174dae aliguori
    if (!(s->lsr & UART_LSR_THRE))
357 81174dae aliguori
        qemu_mod_timer(s->transmit_timer, s->last_xmit_ts + s->char_transmit_time);
358 81174dae aliguori
359 81174dae aliguori
    if (s->lsr & UART_LSR_THRE) {
360 81174dae aliguori
        s->lsr |= UART_LSR_TEMT;
361 81174dae aliguori
        s->thr_ipending = 1;
362 81174dae aliguori
        serial_update_irq(s);
363 81174dae aliguori
    }
364 81174dae aliguori
}
365 81174dae aliguori
366 81174dae aliguori
367 b41a2cd1 bellard
static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val)
368 80cabfad bellard
{
369 b41a2cd1 bellard
    SerialState *s = opaque;
370 3b46e624 ths
371 80cabfad bellard
    addr &= 7;
372 b6601141 Michal Novotny
    DPRINTF("write addr=0x%02x val=0x%02x\n", addr, val);
373 80cabfad bellard
    switch(addr) {
374 80cabfad bellard
    default:
375 80cabfad bellard
    case 0:
376 80cabfad bellard
        if (s->lcr & UART_LCR_DLAB) {
377 80cabfad bellard
            s->divider = (s->divider & 0xff00) | val;
378 f8d179e3 bellard
            serial_update_parameters(s);
379 80cabfad bellard
        } else {
380 81174dae aliguori
            s->thr = (uint8_t) val;
381 81174dae aliguori
            if(s->fcr & UART_FCR_FE) {
382 2f4f22bd Aurelien Jarno
                fifo_put(s, XMIT_FIFO, s->thr);
383 2f4f22bd Aurelien Jarno
                s->thr_ipending = 0;
384 2f4f22bd Aurelien Jarno
                s->lsr &= ~UART_LSR_TEMT;
385 2f4f22bd Aurelien Jarno
                s->lsr &= ~UART_LSR_THRE;
386 2f4f22bd Aurelien Jarno
                serial_update_irq(s);
387 6936bfe5 aurel32
            } else {
388 2f4f22bd Aurelien Jarno
                s->thr_ipending = 0;
389 2f4f22bd Aurelien Jarno
                s->lsr &= ~UART_LSR_THRE;
390 2f4f22bd Aurelien Jarno
                serial_update_irq(s);
391 6936bfe5 aurel32
            }
392 81174dae aliguori
            serial_xmit(s);
393 80cabfad bellard
        }
394 80cabfad bellard
        break;
395 80cabfad bellard
    case 1:
396 80cabfad bellard
        if (s->lcr & UART_LCR_DLAB) {
397 80cabfad bellard
            s->divider = (s->divider & 0x00ff) | (val << 8);
398 f8d179e3 bellard
            serial_update_parameters(s);
399 80cabfad bellard
        } else {
400 60e336db bellard
            s->ier = val & 0x0f;
401 81174dae aliguori
            /* If the backend device is a real serial port, turn polling of the modem
402 81174dae aliguori
               status lines on physical port on or off depending on UART_IER_MSI state */
403 81174dae aliguori
            if (s->poll_msl >= 0) {
404 81174dae aliguori
                if (s->ier & UART_IER_MSI) {
405 81174dae aliguori
                     s->poll_msl = 1;
406 81174dae aliguori
                     serial_update_msl(s);
407 81174dae aliguori
                } else {
408 81174dae aliguori
                     qemu_del_timer(s->modem_status_poll);
409 81174dae aliguori
                     s->poll_msl = 0;
410 81174dae aliguori
                }
411 81174dae aliguori
            }
412 60e336db bellard
            if (s->lsr & UART_LSR_THRE) {
413 60e336db bellard
                s->thr_ipending = 1;
414 81174dae aliguori
                serial_update_irq(s);
415 60e336db bellard
            }
416 80cabfad bellard
        }
417 80cabfad bellard
        break;
418 80cabfad bellard
    case 2:
419 81174dae aliguori
        val = val & 0xFF;
420 81174dae aliguori
421 81174dae aliguori
        if (s->fcr == val)
422 81174dae aliguori
            break;
423 81174dae aliguori
424 81174dae aliguori
        /* Did the enable/disable flag change? If so, make sure FIFOs get flushed */
425 81174dae aliguori
        if ((val ^ s->fcr) & UART_FCR_FE)
426 81174dae aliguori
            val |= UART_FCR_XFR | UART_FCR_RFR;
427 81174dae aliguori
428 81174dae aliguori
        /* FIFO clear */
429 81174dae aliguori
430 81174dae aliguori
        if (val & UART_FCR_RFR) {
431 81174dae aliguori
            qemu_del_timer(s->fifo_timeout_timer);
432 81174dae aliguori
            s->timeout_ipending=0;
433 81174dae aliguori
            fifo_clear(s,RECV_FIFO);
434 81174dae aliguori
        }
435 81174dae aliguori
436 81174dae aliguori
        if (val & UART_FCR_XFR) {
437 81174dae aliguori
            fifo_clear(s,XMIT_FIFO);
438 81174dae aliguori
        }
439 81174dae aliguori
440 81174dae aliguori
        if (val & UART_FCR_FE) {
441 81174dae aliguori
            s->iir |= UART_IIR_FE;
442 81174dae aliguori
            /* Set RECV_FIFO trigger Level */
443 81174dae aliguori
            switch (val & 0xC0) {
444 81174dae aliguori
            case UART_FCR_ITL_1:
445 81174dae aliguori
                s->recv_fifo.itl = 1;
446 81174dae aliguori
                break;
447 81174dae aliguori
            case UART_FCR_ITL_2:
448 81174dae aliguori
                s->recv_fifo.itl = 4;
449 81174dae aliguori
                break;
450 81174dae aliguori
            case UART_FCR_ITL_3:
451 81174dae aliguori
                s->recv_fifo.itl = 8;
452 81174dae aliguori
                break;
453 81174dae aliguori
            case UART_FCR_ITL_4:
454 81174dae aliguori
                s->recv_fifo.itl = 14;
455 81174dae aliguori
                break;
456 81174dae aliguori
            }
457 81174dae aliguori
        } else
458 81174dae aliguori
            s->iir &= ~UART_IIR_FE;
459 81174dae aliguori
460 81174dae aliguori
        /* Set fcr - or at least the bits in it that are supposed to "stick" */
461 81174dae aliguori
        s->fcr = val & 0xC9;
462 81174dae aliguori
        serial_update_irq(s);
463 80cabfad bellard
        break;
464 80cabfad bellard
    case 3:
465 f8d179e3 bellard
        {
466 f8d179e3 bellard
            int break_enable;
467 f8d179e3 bellard
            s->lcr = val;
468 f8d179e3 bellard
            serial_update_parameters(s);
469 f8d179e3 bellard
            break_enable = (val >> 6) & 1;
470 f8d179e3 bellard
            if (break_enable != s->last_break_enable) {
471 f8d179e3 bellard
                s->last_break_enable = break_enable;
472 41084f1b Anthony Liguori
                qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
473 2122c51a bellard
                               &break_enable);
474 f8d179e3 bellard
            }
475 f8d179e3 bellard
        }
476 80cabfad bellard
        break;
477 80cabfad bellard
    case 4:
478 81174dae aliguori
        {
479 81174dae aliguori
            int flags;
480 81174dae aliguori
            int old_mcr = s->mcr;
481 81174dae aliguori
            s->mcr = val & 0x1f;
482 81174dae aliguori
            if (val & UART_MCR_LOOP)
483 81174dae aliguori
                break;
484 81174dae aliguori
485 81174dae aliguori
            if (s->poll_msl >= 0 && old_mcr != s->mcr) {
486 81174dae aliguori
487 41084f1b Anthony Liguori
                qemu_chr_fe_ioctl(s->chr,CHR_IOCTL_SERIAL_GET_TIOCM, &flags);
488 81174dae aliguori
489 81174dae aliguori
                flags &= ~(CHR_TIOCM_RTS | CHR_TIOCM_DTR);
490 81174dae aliguori
491 81174dae aliguori
                if (val & UART_MCR_RTS)
492 81174dae aliguori
                    flags |= CHR_TIOCM_RTS;
493 81174dae aliguori
                if (val & UART_MCR_DTR)
494 81174dae aliguori
                    flags |= CHR_TIOCM_DTR;
495 81174dae aliguori
496 41084f1b Anthony Liguori
                qemu_chr_fe_ioctl(s->chr,CHR_IOCTL_SERIAL_SET_TIOCM, &flags);
497 81174dae aliguori
                /* Update the modem status after a one-character-send wait-time, since there may be a response
498 81174dae aliguori
                   from the device/computer at the other end of the serial line */
499 74475455 Paolo Bonzini
                qemu_mod_timer(s->modem_status_poll, qemu_get_clock_ns(vm_clock) + s->char_transmit_time);
500 81174dae aliguori
            }
501 81174dae aliguori
        }
502 80cabfad bellard
        break;
503 80cabfad bellard
    case 5:
504 80cabfad bellard
        break;
505 80cabfad bellard
    case 6:
506 80cabfad bellard
        break;
507 80cabfad bellard
    case 7:
508 80cabfad bellard
        s->scr = val;
509 80cabfad bellard
        break;
510 80cabfad bellard
    }
511 80cabfad bellard
}
512 80cabfad bellard
513 b41a2cd1 bellard
static uint32_t serial_ioport_read(void *opaque, uint32_t addr)
514 80cabfad bellard
{
515 b41a2cd1 bellard
    SerialState *s = opaque;
516 80cabfad bellard
    uint32_t ret;
517 80cabfad bellard
518 80cabfad bellard
    addr &= 7;
519 80cabfad bellard
    switch(addr) {
520 80cabfad bellard
    default:
521 80cabfad bellard
    case 0:
522 80cabfad bellard
        if (s->lcr & UART_LCR_DLAB) {
523 5fafdf24 ths
            ret = s->divider & 0xff;
524 80cabfad bellard
        } else {
525 81174dae aliguori
            if(s->fcr & UART_FCR_FE) {
526 81174dae aliguori
                ret = fifo_get(s,RECV_FIFO);
527 81174dae aliguori
                if (s->recv_fifo.count == 0)
528 81174dae aliguori
                    s->lsr &= ~(UART_LSR_DR | UART_LSR_BI);
529 81174dae aliguori
                else
530 74475455 Paolo Bonzini
                    qemu_mod_timer(s->fifo_timeout_timer, qemu_get_clock_ns (vm_clock) + s->char_transmit_time * 4);
531 81174dae aliguori
                s->timeout_ipending = 0;
532 81174dae aliguori
            } else {
533 81174dae aliguori
                ret = s->rbr;
534 81174dae aliguori
                s->lsr &= ~(UART_LSR_DR | UART_LSR_BI);
535 81174dae aliguori
            }
536 b41a2cd1 bellard
            serial_update_irq(s);
537 b2a5160c balrog
            if (!(s->mcr & UART_MCR_LOOP)) {
538 b2a5160c balrog
                /* in loopback mode, don't receive any data */
539 b2a5160c balrog
                qemu_chr_accept_input(s->chr);
540 b2a5160c balrog
            }
541 80cabfad bellard
        }
542 80cabfad bellard
        break;
543 80cabfad bellard
    case 1:
544 80cabfad bellard
        if (s->lcr & UART_LCR_DLAB) {
545 80cabfad bellard
            ret = (s->divider >> 8) & 0xff;
546 80cabfad bellard
        } else {
547 80cabfad bellard
            ret = s->ier;
548 80cabfad bellard
        }
549 80cabfad bellard
        break;
550 80cabfad bellard
    case 2:
551 80cabfad bellard
        ret = s->iir;
552 cdee7bdf Aurelien Jarno
        if ((ret & UART_IIR_ID) == UART_IIR_THRI) {
553 80cabfad bellard
            s->thr_ipending = 0;
554 71e605f8 Justin T. Gibbs
            serial_update_irq(s);
555 71e605f8 Justin T. Gibbs
        }
556 80cabfad bellard
        break;
557 80cabfad bellard
    case 3:
558 80cabfad bellard
        ret = s->lcr;
559 80cabfad bellard
        break;
560 80cabfad bellard
    case 4:
561 80cabfad bellard
        ret = s->mcr;
562 80cabfad bellard
        break;
563 80cabfad bellard
    case 5:
564 80cabfad bellard
        ret = s->lsr;
565 71e605f8 Justin T. Gibbs
        /* Clear break and overrun interrupts */
566 71e605f8 Justin T. Gibbs
        if (s->lsr & (UART_LSR_BI|UART_LSR_OE)) {
567 71e605f8 Justin T. Gibbs
            s->lsr &= ~(UART_LSR_BI|UART_LSR_OE);
568 81174dae aliguori
            serial_update_irq(s);
569 81174dae aliguori
        }
570 80cabfad bellard
        break;
571 80cabfad bellard
    case 6:
572 80cabfad bellard
        if (s->mcr & UART_MCR_LOOP) {
573 80cabfad bellard
            /* in loopback, the modem output pins are connected to the
574 80cabfad bellard
               inputs */
575 80cabfad bellard
            ret = (s->mcr & 0x0c) << 4;
576 80cabfad bellard
            ret |= (s->mcr & 0x02) << 3;
577 80cabfad bellard
            ret |= (s->mcr & 0x01) << 5;
578 80cabfad bellard
        } else {
579 81174dae aliguori
            if (s->poll_msl >= 0)
580 81174dae aliguori
                serial_update_msl(s);
581 80cabfad bellard
            ret = s->msr;
582 81174dae aliguori
            /* Clear delta bits & msr int after read, if they were set */
583 81174dae aliguori
            if (s->msr & UART_MSR_ANY_DELTA) {
584 81174dae aliguori
                s->msr &= 0xF0;
585 81174dae aliguori
                serial_update_irq(s);
586 81174dae aliguori
            }
587 80cabfad bellard
        }
588 80cabfad bellard
        break;
589 80cabfad bellard
    case 7:
590 80cabfad bellard
        ret = s->scr;
591 80cabfad bellard
        break;
592 80cabfad bellard
    }
593 b6601141 Michal Novotny
    DPRINTF("read addr=0x%02x val=0x%02x\n", addr, ret);
594 80cabfad bellard
    return ret;
595 80cabfad bellard
}
596 80cabfad bellard
597 82c643ff bellard
static int serial_can_receive(SerialState *s)
598 80cabfad bellard
{
599 81174dae aliguori
    if(s->fcr & UART_FCR_FE) {
600 81174dae aliguori
        if(s->recv_fifo.count < UART_FIFO_LENGTH)
601 81174dae aliguori
        /* Advertise (fifo.itl - fifo.count) bytes when count < ITL, and 1 if above. If UART_FIFO_LENGTH - fifo.count is
602 81174dae aliguori
        advertised the effect will be to almost always fill the fifo completely before the guest has a chance to respond,
603 81174dae aliguori
        effectively overriding the ITL that the guest has set. */
604 81174dae aliguori
             return (s->recv_fifo.count <= s->recv_fifo.itl) ? s->recv_fifo.itl - s->recv_fifo.count : 1;
605 81174dae aliguori
        else
606 81174dae aliguori
             return 0;
607 81174dae aliguori
    } else {
608 80cabfad bellard
    return !(s->lsr & UART_LSR_DR);
609 81174dae aliguori
    }
610 80cabfad bellard
}
611 80cabfad bellard
612 82c643ff bellard
static void serial_receive_break(SerialState *s)
613 80cabfad bellard
{
614 80cabfad bellard
    s->rbr = 0;
615 40ff1624 Jason Wessel
    /* When the LSR_DR is set a null byte is pushed into the fifo */
616 40ff1624 Jason Wessel
    fifo_put(s, RECV_FIFO, '\0');
617 80cabfad bellard
    s->lsr |= UART_LSR_BI | UART_LSR_DR;
618 b41a2cd1 bellard
    serial_update_irq(s);
619 80cabfad bellard
}
620 80cabfad bellard
621 81174dae aliguori
/* There's data in recv_fifo and s->rbr has not been read for 4 char transmit times */
622 81174dae aliguori
static void fifo_timeout_int (void *opaque) {
623 81174dae aliguori
    SerialState *s = opaque;
624 81174dae aliguori
    if (s->recv_fifo.count) {
625 81174dae aliguori
        s->timeout_ipending = 1;
626 81174dae aliguori
        serial_update_irq(s);
627 81174dae aliguori
    }
628 81174dae aliguori
}
629 81174dae aliguori
630 b41a2cd1 bellard
static int serial_can_receive1(void *opaque)
631 80cabfad bellard
{
632 b41a2cd1 bellard
    SerialState *s = opaque;
633 b41a2cd1 bellard
    return serial_can_receive(s);
634 b41a2cd1 bellard
}
635 b41a2cd1 bellard
636 b41a2cd1 bellard
static void serial_receive1(void *opaque, const uint8_t *buf, int size)
637 b41a2cd1 bellard
{
638 b41a2cd1 bellard
    SerialState *s = opaque;
639 9826fd59 Gerd Hoffmann
640 9826fd59 Gerd Hoffmann
    if (s->wakeup) {
641 9826fd59 Gerd Hoffmann
        qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
642 9826fd59 Gerd Hoffmann
    }
643 81174dae aliguori
    if(s->fcr & UART_FCR_FE) {
644 81174dae aliguori
        int i;
645 81174dae aliguori
        for (i = 0; i < size; i++) {
646 81174dae aliguori
            fifo_put(s, RECV_FIFO, buf[i]);
647 81174dae aliguori
        }
648 81174dae aliguori
        s->lsr |= UART_LSR_DR;
649 81174dae aliguori
        /* call the timeout receive callback in 4 char transmit time */
650 74475455 Paolo Bonzini
        qemu_mod_timer(s->fifo_timeout_timer, qemu_get_clock_ns (vm_clock) + s->char_transmit_time * 4);
651 81174dae aliguori
    } else {
652 71e605f8 Justin T. Gibbs
        if (s->lsr & UART_LSR_DR)
653 71e605f8 Justin T. Gibbs
            s->lsr |= UART_LSR_OE;
654 81174dae aliguori
        s->rbr = buf[0];
655 81174dae aliguori
        s->lsr |= UART_LSR_DR;
656 81174dae aliguori
    }
657 81174dae aliguori
    serial_update_irq(s);
658 b41a2cd1 bellard
}
659 80cabfad bellard
660 82c643ff bellard
static void serial_event(void *opaque, int event)
661 82c643ff bellard
{
662 82c643ff bellard
    SerialState *s = opaque;
663 b6601141 Michal Novotny
    DPRINTF("event %x\n", event);
664 82c643ff bellard
    if (event == CHR_EVENT_BREAK)
665 82c643ff bellard
        serial_receive_break(s);
666 82c643ff bellard
}
667 82c643ff bellard
668 d4bfa4d7 Juan Quintela
static void serial_pre_save(void *opaque)
669 8738a8d0 bellard
{
670 d4bfa4d7 Juan Quintela
    SerialState *s = opaque;
671 747791f1 Juan Quintela
    s->fcr_vmstate = s->fcr;
672 8738a8d0 bellard
}
673 8738a8d0 bellard
674 e59fb374 Juan Quintela
static int serial_post_load(void *opaque, int version_id)
675 747791f1 Juan Quintela
{
676 747791f1 Juan Quintela
    SerialState *s = opaque;
677 81174dae aliguori
678 4c18ce94 Juan Quintela
    if (version_id < 3) {
679 4c18ce94 Juan Quintela
        s->fcr_vmstate = 0;
680 4c18ce94 Juan Quintela
    }
681 81174dae aliguori
    /* Initialize fcr via setter to perform essential side-effects */
682 747791f1 Juan Quintela
    serial_ioport_write(s, 0x02, s->fcr_vmstate);
683 9a7c4878 Michal Novotny
    serial_update_parameters(s);
684 8738a8d0 bellard
    return 0;
685 8738a8d0 bellard
}
686 8738a8d0 bellard
687 747791f1 Juan Quintela
static const VMStateDescription vmstate_serial = {
688 747791f1 Juan Quintela
    .name = "serial",
689 747791f1 Juan Quintela
    .version_id = 3,
690 747791f1 Juan Quintela
    .minimum_version_id = 2,
691 747791f1 Juan Quintela
    .pre_save = serial_pre_save,
692 747791f1 Juan Quintela
    .post_load = serial_post_load,
693 747791f1 Juan Quintela
    .fields      = (VMStateField []) {
694 747791f1 Juan Quintela
        VMSTATE_UINT16_V(divider, SerialState, 2),
695 747791f1 Juan Quintela
        VMSTATE_UINT8(rbr, SerialState),
696 747791f1 Juan Quintela
        VMSTATE_UINT8(ier, SerialState),
697 747791f1 Juan Quintela
        VMSTATE_UINT8(iir, SerialState),
698 747791f1 Juan Quintela
        VMSTATE_UINT8(lcr, SerialState),
699 747791f1 Juan Quintela
        VMSTATE_UINT8(mcr, SerialState),
700 747791f1 Juan Quintela
        VMSTATE_UINT8(lsr, SerialState),
701 747791f1 Juan Quintela
        VMSTATE_UINT8(msr, SerialState),
702 747791f1 Juan Quintela
        VMSTATE_UINT8(scr, SerialState),
703 747791f1 Juan Quintela
        VMSTATE_UINT8_V(fcr_vmstate, SerialState, 3),
704 747791f1 Juan Quintela
        VMSTATE_END_OF_LIST()
705 747791f1 Juan Quintela
    }
706 747791f1 Juan Quintela
};
707 747791f1 Juan Quintela
708 b2a5160c balrog
static void serial_reset(void *opaque)
709 b2a5160c balrog
{
710 b2a5160c balrog
    SerialState *s = opaque;
711 b2a5160c balrog
712 b2a5160c balrog
    s->rbr = 0;
713 b2a5160c balrog
    s->ier = 0;
714 b2a5160c balrog
    s->iir = UART_IIR_NO_INT;
715 b2a5160c balrog
    s->lcr = 0;
716 b2a5160c balrog
    s->lsr = UART_LSR_TEMT | UART_LSR_THRE;
717 b2a5160c balrog
    s->msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS;
718 718b8aec Stefan Weil
    /* Default to 9600 baud, 1 start bit, 8 data bits, 1 stop bit, no parity. */
719 81174dae aliguori
    s->divider = 0x0C;
720 81174dae aliguori
    s->mcr = UART_MCR_OUT2;
721 b2a5160c balrog
    s->scr = 0;
722 81174dae aliguori
    s->tsr_retry = 0;
723 718b8aec Stefan Weil
    s->char_transmit_time = (get_ticks_per_sec() / 9600) * 10;
724 81174dae aliguori
    s->poll_msl = 0;
725 81174dae aliguori
726 81174dae aliguori
    fifo_clear(s,RECV_FIFO);
727 81174dae aliguori
    fifo_clear(s,XMIT_FIFO);
728 81174dae aliguori
729 74475455 Paolo Bonzini
    s->last_xmit_ts = qemu_get_clock_ns(vm_clock);
730 b2a5160c balrog
731 b2a5160c balrog
    s->thr_ipending = 0;
732 b2a5160c balrog
    s->last_break_enable = 0;
733 b2a5160c balrog
    qemu_irq_lower(s->irq);
734 b2a5160c balrog
}
735 b2a5160c balrog
736 ac0be998 Gerd Hoffmann
static void serial_init_core(SerialState *s)
737 81174dae aliguori
{
738 ac0be998 Gerd Hoffmann
    if (!s->chr) {
739 387f4a5a Aurelien Jarno
        fprintf(stderr, "Can't create serial device, empty char device\n");
740 387f4a5a Aurelien Jarno
        exit(1);
741 387f4a5a Aurelien Jarno
    }
742 387f4a5a Aurelien Jarno
743 74475455 Paolo Bonzini
    s->modem_status_poll = qemu_new_timer_ns(vm_clock, (QEMUTimerCB *) serial_update_msl, s);
744 81174dae aliguori
745 74475455 Paolo Bonzini
    s->fifo_timeout_timer = qemu_new_timer_ns(vm_clock, (QEMUTimerCB *) fifo_timeout_int, s);
746 74475455 Paolo Bonzini
    s->transmit_timer = qemu_new_timer_ns(vm_clock, (QEMUTimerCB *) serial_xmit, s);
747 81174dae aliguori
748 a08d4367 Jan Kiszka
    qemu_register_reset(serial_reset, s);
749 81174dae aliguori
750 b47543c4 aurel32
    qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1,
751 b47543c4 aurel32
                          serial_event, s);
752 81174dae aliguori
}
753 81174dae aliguori
754 038eaf82 Stefan Weil
/* Change the main reference oscillator frequency. */
755 038eaf82 Stefan Weil
void serial_set_frequency(SerialState *s, uint32_t frequency)
756 038eaf82 Stefan Weil
{
757 038eaf82 Stefan Weil
    s->baudbase = frequency;
758 038eaf82 Stefan Weil
    serial_update_parameters(s);
759 038eaf82 Stefan Weil
}
760 038eaf82 Stefan Weil
761 e8ee28fb Gerd Hoffmann
static const int isa_serial_io[MAX_SERIAL_PORTS] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
762 e8ee28fb Gerd Hoffmann
static const int isa_serial_irq[MAX_SERIAL_PORTS] = { 4, 3, 4, 3 };
763 e8ee28fb Gerd Hoffmann
764 a941ae45 Richard Henderson
static const MemoryRegionPortio serial_portio[] = {
765 a941ae45 Richard Henderson
    { 0, 8, 1, .read = serial_ioport_read, .write = serial_ioport_write },
766 a941ae45 Richard Henderson
    PORTIO_END_OF_LIST()
767 a941ae45 Richard Henderson
};
768 a941ae45 Richard Henderson
769 a941ae45 Richard Henderson
static const MemoryRegionOps serial_io_ops = {
770 a941ae45 Richard Henderson
    .old_portio = serial_portio
771 a941ae45 Richard Henderson
};
772 a941ae45 Richard Henderson
773 ac0be998 Gerd Hoffmann
static int serial_isa_initfn(ISADevice *dev)
774 ac0be998 Gerd Hoffmann
{
775 e8ee28fb Gerd Hoffmann
    static int index;
776 ac0be998 Gerd Hoffmann
    ISASerialState *isa = DO_UPCAST(ISASerialState, dev, dev);
777 ac0be998 Gerd Hoffmann
    SerialState *s = &isa->state;
778 ac0be998 Gerd Hoffmann
779 e8ee28fb Gerd Hoffmann
    if (isa->index == -1)
780 e8ee28fb Gerd Hoffmann
        isa->index = index;
781 e8ee28fb Gerd Hoffmann
    if (isa->index >= MAX_SERIAL_PORTS)
782 e8ee28fb Gerd Hoffmann
        return -1;
783 e8ee28fb Gerd Hoffmann
    if (isa->iobase == -1)
784 e8ee28fb Gerd Hoffmann
        isa->iobase = isa_serial_io[isa->index];
785 e8ee28fb Gerd Hoffmann
    if (isa->isairq == -1)
786 e8ee28fb Gerd Hoffmann
        isa->isairq = isa_serial_irq[isa->index];
787 e8ee28fb Gerd Hoffmann
    index++;
788 e8ee28fb Gerd Hoffmann
789 ac0be998 Gerd Hoffmann
    s->baudbase = 115200;
790 ac0be998 Gerd Hoffmann
    isa_init_irq(dev, &s->irq, isa->isairq);
791 ac0be998 Gerd Hoffmann
    serial_init_core(s);
792 1cc9f514 Jan Kiszka
    qdev_set_legacy_instance_id(&dev->qdev, isa->iobase, 3);
793 ac0be998 Gerd Hoffmann
794 8e8ffc44 Richard Henderson
    memory_region_init_io(&s->io, &serial_io_ops, s, "serial", 8);
795 8e8ffc44 Richard Henderson
    isa_register_ioport(dev, &s->io, isa->iobase);
796 ac0be998 Gerd Hoffmann
    return 0;
797 ac0be998 Gerd Hoffmann
}
798 ac0be998 Gerd Hoffmann
799 1cc9f514 Jan Kiszka
static const VMStateDescription vmstate_isa_serial = {
800 1cc9f514 Jan Kiszka
    .name = "serial",
801 1cc9f514 Jan Kiszka
    .version_id = 3,
802 1cc9f514 Jan Kiszka
    .minimum_version_id = 2,
803 1cc9f514 Jan Kiszka
    .fields      = (VMStateField []) {
804 1cc9f514 Jan Kiszka
        VMSTATE_STRUCT(state, ISASerialState, 0, vmstate_serial, SerialState),
805 1cc9f514 Jan Kiszka
        VMSTATE_END_OF_LIST()
806 1cc9f514 Jan Kiszka
    }
807 1cc9f514 Jan Kiszka
};
808 1cc9f514 Jan Kiszka
809 b6cd0ea1 aurel32
SerialState *serial_init(int base, qemu_irq irq, int baudbase,
810 b6cd0ea1 aurel32
                         CharDriverState *chr)
811 b41a2cd1 bellard
{
812 b41a2cd1 bellard
    SerialState *s;
813 b41a2cd1 bellard
814 7267c094 Anthony Liguori
    s = g_malloc0(sizeof(SerialState));
815 6936bfe5 aurel32
816 ac0be998 Gerd Hoffmann
    s->irq = irq;
817 ac0be998 Gerd Hoffmann
    s->baudbase = baudbase;
818 ac0be998 Gerd Hoffmann
    s->chr = chr;
819 ac0be998 Gerd Hoffmann
    serial_init_core(s);
820 b41a2cd1 bellard
821 0be71e32 Alex Williamson
    vmstate_register(NULL, base, &vmstate_serial, s);
822 8738a8d0 bellard
823 b41a2cd1 bellard
    register_ioport_write(base, 8, 1, serial_ioport_write, s);
824 b41a2cd1 bellard
    register_ioport_read(base, 8, 1, serial_ioport_read, s);
825 b41a2cd1 bellard
    return s;
826 80cabfad bellard
}
827 e5d13e2f bellard
828 e5d13e2f bellard
/* Memory mapped interface */
829 8e8ffc44 Richard Henderson
static uint64_t serial_mm_read(void *opaque, target_phys_addr_t addr,
830 8e8ffc44 Richard Henderson
                               unsigned size)
831 e5d13e2f bellard
{
832 e5d13e2f bellard
    SerialState *s = opaque;
833 8e8ffc44 Richard Henderson
    return serial_ioport_read(s, addr >> s->it_shift);
834 e5d13e2f bellard
}
835 e5d13e2f bellard
836 8e8ffc44 Richard Henderson
static void serial_mm_write(void *opaque, target_phys_addr_t addr,
837 8e8ffc44 Richard Henderson
                            uint64_t value, unsigned size)
838 2d48377a Blue Swirl
{
839 2d48377a Blue Swirl
    SerialState *s = opaque;
840 8e8ffc44 Richard Henderson
    value &= ~0u >> (32 - (size * 8));
841 2d48377a Blue Swirl
    serial_ioport_write(s, addr >> s->it_shift, value);
842 2d48377a Blue Swirl
}
843 2d48377a Blue Swirl
844 8e8ffc44 Richard Henderson
static const MemoryRegionOps serial_mm_ops[3] = {
845 8e8ffc44 Richard Henderson
    [DEVICE_NATIVE_ENDIAN] = {
846 8e8ffc44 Richard Henderson
        .read = serial_mm_read,
847 8e8ffc44 Richard Henderson
        .write = serial_mm_write,
848 8e8ffc44 Richard Henderson
        .endianness = DEVICE_NATIVE_ENDIAN,
849 8e8ffc44 Richard Henderson
    },
850 8e8ffc44 Richard Henderson
    [DEVICE_LITTLE_ENDIAN] = {
851 8e8ffc44 Richard Henderson
        .read = serial_mm_read,
852 8e8ffc44 Richard Henderson
        .write = serial_mm_write,
853 8e8ffc44 Richard Henderson
        .endianness = DEVICE_LITTLE_ENDIAN,
854 8e8ffc44 Richard Henderson
    },
855 8e8ffc44 Richard Henderson
    [DEVICE_BIG_ENDIAN] = {
856 8e8ffc44 Richard Henderson
        .read = serial_mm_read,
857 8e8ffc44 Richard Henderson
        .write = serial_mm_write,
858 8e8ffc44 Richard Henderson
        .endianness = DEVICE_BIG_ENDIAN,
859 8e8ffc44 Richard Henderson
    },
860 e5d13e2f bellard
};
861 e5d13e2f bellard
862 39186d8a Richard Henderson
SerialState *serial_mm_init(MemoryRegion *address_space,
863 39186d8a Richard Henderson
                            target_phys_addr_t base, int it_shift,
864 39186d8a Richard Henderson
                            qemu_irq irq, int baudbase,
865 39186d8a Richard Henderson
                            CharDriverState *chr, enum device_endian end)
866 e5d13e2f bellard
{
867 e5d13e2f bellard
    SerialState *s;
868 e5d13e2f bellard
869 7267c094 Anthony Liguori
    s = g_malloc0(sizeof(SerialState));
870 81174dae aliguori
871 e5d13e2f bellard
    s->it_shift = it_shift;
872 ac0be998 Gerd Hoffmann
    s->irq = irq;
873 ac0be998 Gerd Hoffmann
    s->baudbase = baudbase;
874 ac0be998 Gerd Hoffmann
    s->chr = chr;
875 e5d13e2f bellard
876 ac0be998 Gerd Hoffmann
    serial_init_core(s);
877 0be71e32 Alex Williamson
    vmstate_register(NULL, base, &vmstate_serial, s);
878 e5d13e2f bellard
879 8e8ffc44 Richard Henderson
    memory_region_init_io(&s->io, &serial_mm_ops[end], s,
880 8e8ffc44 Richard Henderson
                          "serial", 8 << it_shift);
881 39186d8a Richard Henderson
    memory_region_add_subregion(address_space, base, &s->io);
882 2ff0c7c3 Richard Henderson
883 81174dae aliguori
    serial_update_msl(s);
884 e5d13e2f bellard
    return s;
885 e5d13e2f bellard
}
886 ac0be998 Gerd Hoffmann
887 39bffca2 Anthony Liguori
static Property serial_isa_properties[] = {
888 39bffca2 Anthony Liguori
    DEFINE_PROP_UINT32("index", ISASerialState, index,   -1),
889 39bffca2 Anthony Liguori
    DEFINE_PROP_HEX32("iobase", ISASerialState, iobase,  -1),
890 39bffca2 Anthony Liguori
    DEFINE_PROP_UINT32("irq",   ISASerialState, isairq,  -1),
891 39bffca2 Anthony Liguori
    DEFINE_PROP_CHR("chardev",  ISASerialState, state.chr),
892 9826fd59 Gerd Hoffmann
    DEFINE_PROP_UINT32("wakeup", ISASerialState, state.wakeup, 0),
893 39bffca2 Anthony Liguori
    DEFINE_PROP_END_OF_LIST(),
894 39bffca2 Anthony Liguori
};
895 39bffca2 Anthony Liguori
896 8f04ee08 Anthony Liguori
static void serial_isa_class_initfn(ObjectClass *klass, void *data)
897 8f04ee08 Anthony Liguori
{
898 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
899 8f04ee08 Anthony Liguori
    ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
900 8f04ee08 Anthony Liguori
    ic->init = serial_isa_initfn;
901 39bffca2 Anthony Liguori
    dc->vmsd = &vmstate_isa_serial;
902 39bffca2 Anthony Liguori
    dc->props = serial_isa_properties;
903 8f04ee08 Anthony Liguori
}
904 8f04ee08 Anthony Liguori
905 39bffca2 Anthony Liguori
static TypeInfo serial_isa_info = {
906 39bffca2 Anthony Liguori
    .name          = "isa-serial",
907 39bffca2 Anthony Liguori
    .parent        = TYPE_ISA_DEVICE,
908 39bffca2 Anthony Liguori
    .instance_size = sizeof(ISASerialState),
909 39bffca2 Anthony Liguori
    .class_init    = serial_isa_class_initfn,
910 ac0be998 Gerd Hoffmann
};
911 ac0be998 Gerd Hoffmann
912 83f7d43a Andreas Färber
static void serial_register_types(void)
913 ac0be998 Gerd Hoffmann
{
914 39bffca2 Anthony Liguori
    type_register_static(&serial_isa_info);
915 ac0be998 Gerd Hoffmann
}
916 ac0be998 Gerd Hoffmann
917 83f7d43a Andreas Färber
type_init(serial_register_types)