Statistics
| Branch: | Revision:

root / hw / serial.c @ be62a2eb

History | View | Annotate | Download (27 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 81174dae aliguori
143 81174dae aliguori
    uint64_t last_xmit_ts;              /* Time when the last byte was successfully sent out of the tsr */
144 81174dae aliguori
    SerialFIFO recv_fifo;
145 81174dae aliguori
    SerialFIFO xmit_fifo;
146 81174dae aliguori
147 81174dae aliguori
    struct QEMUTimer *fifo_timeout_timer;
148 81174dae aliguori
    int timeout_ipending;                   /* timeout interrupt pending state */
149 81174dae aliguori
    struct QEMUTimer *transmit_timer;
150 81174dae aliguori
151 81174dae aliguori
152 81174dae aliguori
    uint64_t char_transmit_time;               /* time to transmit a char in ticks*/
153 81174dae aliguori
    int poll_msl;
154 81174dae aliguori
155 81174dae aliguori
    struct QEMUTimer *modem_status_poll;
156 8e8ffc44 Richard Henderson
    MemoryRegion io;
157 b41a2cd1 bellard
};
158 80cabfad bellard
159 ac0be998 Gerd Hoffmann
typedef struct ISASerialState {
160 ac0be998 Gerd Hoffmann
    ISADevice dev;
161 e8ee28fb Gerd Hoffmann
    uint32_t index;
162 ac0be998 Gerd Hoffmann
    uint32_t iobase;
163 ac0be998 Gerd Hoffmann
    uint32_t isairq;
164 ac0be998 Gerd Hoffmann
    SerialState state;
165 ac0be998 Gerd Hoffmann
} ISASerialState;
166 ac0be998 Gerd Hoffmann
167 81174dae aliguori
static void serial_receive1(void *opaque, const uint8_t *buf, int size);
168 b2a5160c balrog
169 81174dae aliguori
static void fifo_clear(SerialState *s, int fifo)
170 80cabfad bellard
{
171 81174dae aliguori
    SerialFIFO *f = (fifo) ? &s->recv_fifo : &s->xmit_fifo;
172 81174dae aliguori
    memset(f->data, 0, UART_FIFO_LENGTH);
173 81174dae aliguori
    f->count = 0;
174 81174dae aliguori
    f->head = 0;
175 81174dae aliguori
    f->tail = 0;
176 80cabfad bellard
}
177 80cabfad bellard
178 81174dae aliguori
static int fifo_put(SerialState *s, int fifo, uint8_t chr)
179 6936bfe5 aurel32
{
180 81174dae aliguori
    SerialFIFO *f = (fifo) ? &s->recv_fifo : &s->xmit_fifo;
181 6936bfe5 aurel32
182 71e605f8 Justin T. Gibbs
    /* Receive overruns do not overwrite FIFO contents. */
183 71e605f8 Justin T. Gibbs
    if (fifo == XMIT_FIFO || f->count < UART_FIFO_LENGTH) {
184 6936bfe5 aurel32
185 71e605f8 Justin T. Gibbs
        f->data[f->head++] = chr;
186 71e605f8 Justin T. Gibbs
187 71e605f8 Justin T. Gibbs
        if (f->head == UART_FIFO_LENGTH)
188 71e605f8 Justin T. Gibbs
            f->head = 0;
189 71e605f8 Justin T. Gibbs
    }
190 71e605f8 Justin T. Gibbs
191 71e605f8 Justin T. Gibbs
    if (f->count < UART_FIFO_LENGTH)
192 71e605f8 Justin T. Gibbs
        f->count++;
193 71e605f8 Justin T. Gibbs
    else if (fifo == RECV_FIFO)
194 71e605f8 Justin T. Gibbs
        s->lsr |= UART_LSR_OE;
195 81174dae aliguori
196 81174dae aliguori
    return 1;
197 81174dae aliguori
}
198 81174dae aliguori
199 81174dae aliguori
static uint8_t fifo_get(SerialState *s, int fifo)
200 81174dae aliguori
{
201 81174dae aliguori
    SerialFIFO *f = (fifo) ? &s->recv_fifo : &s->xmit_fifo;
202 81174dae aliguori
    uint8_t c;
203 81174dae aliguori
204 81174dae aliguori
    if(f->count == 0)
205 81174dae aliguori
        return 0;
206 81174dae aliguori
207 81174dae aliguori
    c = f->data[f->tail++];
208 81174dae aliguori
    if (f->tail == UART_FIFO_LENGTH)
209 81174dae aliguori
        f->tail = 0;
210 81174dae aliguori
    f->count--;
211 81174dae aliguori
212 81174dae aliguori
    return c;
213 81174dae aliguori
}
214 6936bfe5 aurel32
215 81174dae aliguori
static void serial_update_irq(SerialState *s)
216 81174dae aliguori
{
217 81174dae aliguori
    uint8_t tmp_iir = UART_IIR_NO_INT;
218 81174dae aliguori
219 81174dae aliguori
    if ((s->ier & UART_IER_RLSI) && (s->lsr & UART_LSR_INT_ANY)) {
220 81174dae aliguori
        tmp_iir = UART_IIR_RLSI;
221 5628a626 balrog
    } else if ((s->ier & UART_IER_RDI) && s->timeout_ipending) {
222 c9a33054 balrog
        /* Note that(s->ier & UART_IER_RDI) can mask this interrupt,
223 c9a33054 balrog
         * this is not in the specification but is observed on existing
224 c9a33054 balrog
         * hardware.  */
225 81174dae aliguori
        tmp_iir = UART_IIR_CTI;
226 2d6ee8e7 Juergen Lock
    } else if ((s->ier & UART_IER_RDI) && (s->lsr & UART_LSR_DR) &&
227 2d6ee8e7 Juergen Lock
               (!(s->fcr & UART_FCR_FE) ||
228 2d6ee8e7 Juergen Lock
                s->recv_fifo.count >= s->recv_fifo.itl)) {
229 2d6ee8e7 Juergen Lock
        tmp_iir = UART_IIR_RDI;
230 81174dae aliguori
    } else if ((s->ier & UART_IER_THRI) && s->thr_ipending) {
231 81174dae aliguori
        tmp_iir = UART_IIR_THRI;
232 81174dae aliguori
    } else if ((s->ier & UART_IER_MSI) && (s->msr & UART_MSR_ANY_DELTA)) {
233 81174dae aliguori
        tmp_iir = UART_IIR_MSI;
234 81174dae aliguori
    }
235 81174dae aliguori
236 81174dae aliguori
    s->iir = tmp_iir | (s->iir & 0xF0);
237 81174dae aliguori
238 81174dae aliguori
    if (tmp_iir != UART_IIR_NO_INT) {
239 81174dae aliguori
        qemu_irq_raise(s->irq);
240 81174dae aliguori
    } else {
241 81174dae aliguori
        qemu_irq_lower(s->irq);
242 6936bfe5 aurel32
    }
243 6936bfe5 aurel32
}
244 6936bfe5 aurel32
245 f8d179e3 bellard
static void serial_update_parameters(SerialState *s)
246 f8d179e3 bellard
{
247 81174dae aliguori
    int speed, parity, data_bits, stop_bits, frame_size;
248 2122c51a bellard
    QEMUSerialSetParams ssp;
249 f8d179e3 bellard
250 81174dae aliguori
    if (s->divider == 0)
251 81174dae aliguori
        return;
252 81174dae aliguori
253 718b8aec Stefan Weil
    /* Start bit. */
254 81174dae aliguori
    frame_size = 1;
255 f8d179e3 bellard
    if (s->lcr & 0x08) {
256 718b8aec Stefan Weil
        /* Parity bit. */
257 718b8aec Stefan Weil
        frame_size++;
258 f8d179e3 bellard
        if (s->lcr & 0x10)
259 f8d179e3 bellard
            parity = 'E';
260 f8d179e3 bellard
        else
261 f8d179e3 bellard
            parity = 'O';
262 f8d179e3 bellard
    } else {
263 f8d179e3 bellard
            parity = 'N';
264 f8d179e3 bellard
    }
265 5fafdf24 ths
    if (s->lcr & 0x04)
266 f8d179e3 bellard
        stop_bits = 2;
267 f8d179e3 bellard
    else
268 f8d179e3 bellard
        stop_bits = 1;
269 81174dae aliguori
270 f8d179e3 bellard
    data_bits = (s->lcr & 0x03) + 5;
271 81174dae aliguori
    frame_size += data_bits + stop_bits;
272 b6cd0ea1 aurel32
    speed = s->baudbase / s->divider;
273 2122c51a bellard
    ssp.speed = speed;
274 2122c51a bellard
    ssp.parity = parity;
275 2122c51a bellard
    ssp.data_bits = data_bits;
276 2122c51a bellard
    ssp.stop_bits = stop_bits;
277 6ee093c9 Juan Quintela
    s->char_transmit_time =  (get_ticks_per_sec() / speed) * frame_size;
278 41084f1b Anthony Liguori
    qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
279 b6601141 Michal Novotny
280 b6601141 Michal Novotny
    DPRINTF("speed=%d parity=%c data=%d stop=%d\n",
281 f8d179e3 bellard
           speed, parity, data_bits, stop_bits);
282 f8d179e3 bellard
}
283 f8d179e3 bellard
284 81174dae aliguori
static void serial_update_msl(SerialState *s)
285 81174dae aliguori
{
286 81174dae aliguori
    uint8_t omsr;
287 81174dae aliguori
    int flags;
288 81174dae aliguori
289 81174dae aliguori
    qemu_del_timer(s->modem_status_poll);
290 81174dae aliguori
291 41084f1b Anthony Liguori
    if (qemu_chr_fe_ioctl(s->chr,CHR_IOCTL_SERIAL_GET_TIOCM, &flags) == -ENOTSUP) {
292 81174dae aliguori
        s->poll_msl = -1;
293 81174dae aliguori
        return;
294 81174dae aliguori
    }
295 81174dae aliguori
296 81174dae aliguori
    omsr = s->msr;
297 81174dae aliguori
298 81174dae aliguori
    s->msr = (flags & CHR_TIOCM_CTS) ? s->msr | UART_MSR_CTS : s->msr & ~UART_MSR_CTS;
299 81174dae aliguori
    s->msr = (flags & CHR_TIOCM_DSR) ? s->msr | UART_MSR_DSR : s->msr & ~UART_MSR_DSR;
300 81174dae aliguori
    s->msr = (flags & CHR_TIOCM_CAR) ? s->msr | UART_MSR_DCD : s->msr & ~UART_MSR_DCD;
301 81174dae aliguori
    s->msr = (flags & CHR_TIOCM_RI) ? s->msr | UART_MSR_RI : s->msr & ~UART_MSR_RI;
302 81174dae aliguori
303 81174dae aliguori
    if (s->msr != omsr) {
304 81174dae aliguori
         /* Set delta bits */
305 81174dae aliguori
         s->msr = s->msr | ((s->msr >> 4) ^ (omsr >> 4));
306 81174dae aliguori
         /* UART_MSR_TERI only if change was from 1 -> 0 */
307 81174dae aliguori
         if ((s->msr & UART_MSR_TERI) && !(omsr & UART_MSR_RI))
308 81174dae aliguori
             s->msr &= ~UART_MSR_TERI;
309 81174dae aliguori
         serial_update_irq(s);
310 81174dae aliguori
    }
311 81174dae aliguori
312 81174dae aliguori
    /* The real 16550A apparently has a 250ns response latency to line status changes.
313 81174dae aliguori
       We'll be lazy and poll only every 10ms, and only poll it at all if MSI interrupts are turned on */
314 81174dae aliguori
315 81174dae aliguori
    if (s->poll_msl)
316 74475455 Paolo Bonzini
        qemu_mod_timer(s->modem_status_poll, qemu_get_clock_ns(vm_clock) + get_ticks_per_sec() / 100);
317 81174dae aliguori
}
318 81174dae aliguori
319 81174dae aliguori
static void serial_xmit(void *opaque)
320 81174dae aliguori
{
321 81174dae aliguori
    SerialState *s = opaque;
322 74475455 Paolo Bonzini
    uint64_t new_xmit_ts = qemu_get_clock_ns(vm_clock);
323 81174dae aliguori
324 81174dae aliguori
    if (s->tsr_retry <= 0) {
325 81174dae aliguori
        if (s->fcr & UART_FCR_FE) {
326 81174dae aliguori
            s->tsr = fifo_get(s,XMIT_FIFO);
327 81174dae aliguori
            if (!s->xmit_fifo.count)
328 81174dae aliguori
                s->lsr |= UART_LSR_THRE;
329 81174dae aliguori
        } else {
330 81174dae aliguori
            s->tsr = s->thr;
331 81174dae aliguori
            s->lsr |= UART_LSR_THRE;
332 81174dae aliguori
        }
333 81174dae aliguori
    }
334 81174dae aliguori
335 81174dae aliguori
    if (s->mcr & UART_MCR_LOOP) {
336 81174dae aliguori
        /* in loopback mode, say that we just received a char */
337 81174dae aliguori
        serial_receive1(s, &s->tsr, 1);
338 2cc6e0a1 Anthony Liguori
    } else if (qemu_chr_fe_write(s->chr, &s->tsr, 1) != 1) {
339 81174dae aliguori
        if ((s->tsr_retry > 0) && (s->tsr_retry <= MAX_XMIT_RETRY)) {
340 81174dae aliguori
            s->tsr_retry++;
341 81174dae aliguori
            qemu_mod_timer(s->transmit_timer,  new_xmit_ts + s->char_transmit_time);
342 81174dae aliguori
            return;
343 81174dae aliguori
        } else if (s->poll_msl < 0) {
344 81174dae aliguori
            /* If we exceed MAX_XMIT_RETRY and the backend is not a real serial port, then
345 81174dae aliguori
            drop any further failed writes instantly, until we get one that goes through.
346 81174dae aliguori
            This is to prevent guests that log to unconnected pipes or pty's from stalling. */
347 81174dae aliguori
            s->tsr_retry = -1;
348 81174dae aliguori
        }
349 81174dae aliguori
    }
350 81174dae aliguori
    else {
351 81174dae aliguori
        s->tsr_retry = 0;
352 81174dae aliguori
    }
353 81174dae aliguori
354 74475455 Paolo Bonzini
    s->last_xmit_ts = qemu_get_clock_ns(vm_clock);
355 81174dae aliguori
    if (!(s->lsr & UART_LSR_THRE))
356 81174dae aliguori
        qemu_mod_timer(s->transmit_timer, s->last_xmit_ts + s->char_transmit_time);
357 81174dae aliguori
358 81174dae aliguori
    if (s->lsr & UART_LSR_THRE) {
359 81174dae aliguori
        s->lsr |= UART_LSR_TEMT;
360 81174dae aliguori
        s->thr_ipending = 1;
361 81174dae aliguori
        serial_update_irq(s);
362 81174dae aliguori
    }
363 81174dae aliguori
}
364 81174dae aliguori
365 81174dae aliguori
366 b41a2cd1 bellard
static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val)
367 80cabfad bellard
{
368 b41a2cd1 bellard
    SerialState *s = opaque;
369 3b46e624 ths
370 80cabfad bellard
    addr &= 7;
371 b6601141 Michal Novotny
    DPRINTF("write addr=0x%02x val=0x%02x\n", addr, val);
372 80cabfad bellard
    switch(addr) {
373 80cabfad bellard
    default:
374 80cabfad bellard
    case 0:
375 80cabfad bellard
        if (s->lcr & UART_LCR_DLAB) {
376 80cabfad bellard
            s->divider = (s->divider & 0xff00) | val;
377 f8d179e3 bellard
            serial_update_parameters(s);
378 80cabfad bellard
        } else {
379 81174dae aliguori
            s->thr = (uint8_t) val;
380 81174dae aliguori
            if(s->fcr & UART_FCR_FE) {
381 2f4f22bd Aurelien Jarno
                fifo_put(s, XMIT_FIFO, s->thr);
382 2f4f22bd Aurelien Jarno
                s->thr_ipending = 0;
383 2f4f22bd Aurelien Jarno
                s->lsr &= ~UART_LSR_TEMT;
384 2f4f22bd Aurelien Jarno
                s->lsr &= ~UART_LSR_THRE;
385 2f4f22bd Aurelien Jarno
                serial_update_irq(s);
386 6936bfe5 aurel32
            } else {
387 2f4f22bd Aurelien Jarno
                s->thr_ipending = 0;
388 2f4f22bd Aurelien Jarno
                s->lsr &= ~UART_LSR_THRE;
389 2f4f22bd Aurelien Jarno
                serial_update_irq(s);
390 6936bfe5 aurel32
            }
391 81174dae aliguori
            serial_xmit(s);
392 80cabfad bellard
        }
393 80cabfad bellard
        break;
394 80cabfad bellard
    case 1:
395 80cabfad bellard
        if (s->lcr & UART_LCR_DLAB) {
396 80cabfad bellard
            s->divider = (s->divider & 0x00ff) | (val << 8);
397 f8d179e3 bellard
            serial_update_parameters(s);
398 80cabfad bellard
        } else {
399 60e336db bellard
            s->ier = val & 0x0f;
400 81174dae aliguori
            /* If the backend device is a real serial port, turn polling of the modem
401 81174dae aliguori
               status lines on physical port on or off depending on UART_IER_MSI state */
402 81174dae aliguori
            if (s->poll_msl >= 0) {
403 81174dae aliguori
                if (s->ier & UART_IER_MSI) {
404 81174dae aliguori
                     s->poll_msl = 1;
405 81174dae aliguori
                     serial_update_msl(s);
406 81174dae aliguori
                } else {
407 81174dae aliguori
                     qemu_del_timer(s->modem_status_poll);
408 81174dae aliguori
                     s->poll_msl = 0;
409 81174dae aliguori
                }
410 81174dae aliguori
            }
411 60e336db bellard
            if (s->lsr & UART_LSR_THRE) {
412 60e336db bellard
                s->thr_ipending = 1;
413 81174dae aliguori
                serial_update_irq(s);
414 60e336db bellard
            }
415 80cabfad bellard
        }
416 80cabfad bellard
        break;
417 80cabfad bellard
    case 2:
418 81174dae aliguori
        val = val & 0xFF;
419 81174dae aliguori
420 81174dae aliguori
        if (s->fcr == val)
421 81174dae aliguori
            break;
422 81174dae aliguori
423 81174dae aliguori
        /* Did the enable/disable flag change? If so, make sure FIFOs get flushed */
424 81174dae aliguori
        if ((val ^ s->fcr) & UART_FCR_FE)
425 81174dae aliguori
            val |= UART_FCR_XFR | UART_FCR_RFR;
426 81174dae aliguori
427 81174dae aliguori
        /* FIFO clear */
428 81174dae aliguori
429 81174dae aliguori
        if (val & UART_FCR_RFR) {
430 81174dae aliguori
            qemu_del_timer(s->fifo_timeout_timer);
431 81174dae aliguori
            s->timeout_ipending=0;
432 81174dae aliguori
            fifo_clear(s,RECV_FIFO);
433 81174dae aliguori
        }
434 81174dae aliguori
435 81174dae aliguori
        if (val & UART_FCR_XFR) {
436 81174dae aliguori
            fifo_clear(s,XMIT_FIFO);
437 81174dae aliguori
        }
438 81174dae aliguori
439 81174dae aliguori
        if (val & UART_FCR_FE) {
440 81174dae aliguori
            s->iir |= UART_IIR_FE;
441 81174dae aliguori
            /* Set RECV_FIFO trigger Level */
442 81174dae aliguori
            switch (val & 0xC0) {
443 81174dae aliguori
            case UART_FCR_ITL_1:
444 81174dae aliguori
                s->recv_fifo.itl = 1;
445 81174dae aliguori
                break;
446 81174dae aliguori
            case UART_FCR_ITL_2:
447 81174dae aliguori
                s->recv_fifo.itl = 4;
448 81174dae aliguori
                break;
449 81174dae aliguori
            case UART_FCR_ITL_3:
450 81174dae aliguori
                s->recv_fifo.itl = 8;
451 81174dae aliguori
                break;
452 81174dae aliguori
            case UART_FCR_ITL_4:
453 81174dae aliguori
                s->recv_fifo.itl = 14;
454 81174dae aliguori
                break;
455 81174dae aliguori
            }
456 81174dae aliguori
        } else
457 81174dae aliguori
            s->iir &= ~UART_IIR_FE;
458 81174dae aliguori
459 81174dae aliguori
        /* Set fcr - or at least the bits in it that are supposed to "stick" */
460 81174dae aliguori
        s->fcr = val & 0xC9;
461 81174dae aliguori
        serial_update_irq(s);
462 80cabfad bellard
        break;
463 80cabfad bellard
    case 3:
464 f8d179e3 bellard
        {
465 f8d179e3 bellard
            int break_enable;
466 f8d179e3 bellard
            s->lcr = val;
467 f8d179e3 bellard
            serial_update_parameters(s);
468 f8d179e3 bellard
            break_enable = (val >> 6) & 1;
469 f8d179e3 bellard
            if (break_enable != s->last_break_enable) {
470 f8d179e3 bellard
                s->last_break_enable = break_enable;
471 41084f1b Anthony Liguori
                qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
472 2122c51a bellard
                               &break_enable);
473 f8d179e3 bellard
            }
474 f8d179e3 bellard
        }
475 80cabfad bellard
        break;
476 80cabfad bellard
    case 4:
477 81174dae aliguori
        {
478 81174dae aliguori
            int flags;
479 81174dae aliguori
            int old_mcr = s->mcr;
480 81174dae aliguori
            s->mcr = val & 0x1f;
481 81174dae aliguori
            if (val & UART_MCR_LOOP)
482 81174dae aliguori
                break;
483 81174dae aliguori
484 81174dae aliguori
            if (s->poll_msl >= 0 && old_mcr != s->mcr) {
485 81174dae aliguori
486 41084f1b Anthony Liguori
                qemu_chr_fe_ioctl(s->chr,CHR_IOCTL_SERIAL_GET_TIOCM, &flags);
487 81174dae aliguori
488 81174dae aliguori
                flags &= ~(CHR_TIOCM_RTS | CHR_TIOCM_DTR);
489 81174dae aliguori
490 81174dae aliguori
                if (val & UART_MCR_RTS)
491 81174dae aliguori
                    flags |= CHR_TIOCM_RTS;
492 81174dae aliguori
                if (val & UART_MCR_DTR)
493 81174dae aliguori
                    flags |= CHR_TIOCM_DTR;
494 81174dae aliguori
495 41084f1b Anthony Liguori
                qemu_chr_fe_ioctl(s->chr,CHR_IOCTL_SERIAL_SET_TIOCM, &flags);
496 81174dae aliguori
                /* Update the modem status after a one-character-send wait-time, since there may be a response
497 81174dae aliguori
                   from the device/computer at the other end of the serial line */
498 74475455 Paolo Bonzini
                qemu_mod_timer(s->modem_status_poll, qemu_get_clock_ns(vm_clock) + s->char_transmit_time);
499 81174dae aliguori
            }
500 81174dae aliguori
        }
501 80cabfad bellard
        break;
502 80cabfad bellard
    case 5:
503 80cabfad bellard
        break;
504 80cabfad bellard
    case 6:
505 80cabfad bellard
        break;
506 80cabfad bellard
    case 7:
507 80cabfad bellard
        s->scr = val;
508 80cabfad bellard
        break;
509 80cabfad bellard
    }
510 80cabfad bellard
}
511 80cabfad bellard
512 b41a2cd1 bellard
static uint32_t serial_ioport_read(void *opaque, uint32_t addr)
513 80cabfad bellard
{
514 b41a2cd1 bellard
    SerialState *s = opaque;
515 80cabfad bellard
    uint32_t ret;
516 80cabfad bellard
517 80cabfad bellard
    addr &= 7;
518 80cabfad bellard
    switch(addr) {
519 80cabfad bellard
    default:
520 80cabfad bellard
    case 0:
521 80cabfad bellard
        if (s->lcr & UART_LCR_DLAB) {
522 5fafdf24 ths
            ret = s->divider & 0xff;
523 80cabfad bellard
        } else {
524 81174dae aliguori
            if(s->fcr & UART_FCR_FE) {
525 81174dae aliguori
                ret = fifo_get(s,RECV_FIFO);
526 81174dae aliguori
                if (s->recv_fifo.count == 0)
527 81174dae aliguori
                    s->lsr &= ~(UART_LSR_DR | UART_LSR_BI);
528 81174dae aliguori
                else
529 74475455 Paolo Bonzini
                    qemu_mod_timer(s->fifo_timeout_timer, qemu_get_clock_ns (vm_clock) + s->char_transmit_time * 4);
530 81174dae aliguori
                s->timeout_ipending = 0;
531 81174dae aliguori
            } else {
532 81174dae aliguori
                ret = s->rbr;
533 81174dae aliguori
                s->lsr &= ~(UART_LSR_DR | UART_LSR_BI);
534 81174dae aliguori
            }
535 b41a2cd1 bellard
            serial_update_irq(s);
536 b2a5160c balrog
            if (!(s->mcr & UART_MCR_LOOP)) {
537 b2a5160c balrog
                /* in loopback mode, don't receive any data */
538 b2a5160c balrog
                qemu_chr_accept_input(s->chr);
539 b2a5160c balrog
            }
540 80cabfad bellard
        }
541 80cabfad bellard
        break;
542 80cabfad bellard
    case 1:
543 80cabfad bellard
        if (s->lcr & UART_LCR_DLAB) {
544 80cabfad bellard
            ret = (s->divider >> 8) & 0xff;
545 80cabfad bellard
        } else {
546 80cabfad bellard
            ret = s->ier;
547 80cabfad bellard
        }
548 80cabfad bellard
        break;
549 80cabfad bellard
    case 2:
550 80cabfad bellard
        ret = s->iir;
551 cdee7bdf Aurelien Jarno
        if ((ret & UART_IIR_ID) == UART_IIR_THRI) {
552 80cabfad bellard
            s->thr_ipending = 0;
553 71e605f8 Justin T. Gibbs
            serial_update_irq(s);
554 71e605f8 Justin T. Gibbs
        }
555 80cabfad bellard
        break;
556 80cabfad bellard
    case 3:
557 80cabfad bellard
        ret = s->lcr;
558 80cabfad bellard
        break;
559 80cabfad bellard
    case 4:
560 80cabfad bellard
        ret = s->mcr;
561 80cabfad bellard
        break;
562 80cabfad bellard
    case 5:
563 80cabfad bellard
        ret = s->lsr;
564 71e605f8 Justin T. Gibbs
        /* Clear break and overrun interrupts */
565 71e605f8 Justin T. Gibbs
        if (s->lsr & (UART_LSR_BI|UART_LSR_OE)) {
566 71e605f8 Justin T. Gibbs
            s->lsr &= ~(UART_LSR_BI|UART_LSR_OE);
567 81174dae aliguori
            serial_update_irq(s);
568 81174dae aliguori
        }
569 80cabfad bellard
        break;
570 80cabfad bellard
    case 6:
571 80cabfad bellard
        if (s->mcr & UART_MCR_LOOP) {
572 80cabfad bellard
            /* in loopback, the modem output pins are connected to the
573 80cabfad bellard
               inputs */
574 80cabfad bellard
            ret = (s->mcr & 0x0c) << 4;
575 80cabfad bellard
            ret |= (s->mcr & 0x02) << 3;
576 80cabfad bellard
            ret |= (s->mcr & 0x01) << 5;
577 80cabfad bellard
        } else {
578 81174dae aliguori
            if (s->poll_msl >= 0)
579 81174dae aliguori
                serial_update_msl(s);
580 80cabfad bellard
            ret = s->msr;
581 81174dae aliguori
            /* Clear delta bits & msr int after read, if they were set */
582 81174dae aliguori
            if (s->msr & UART_MSR_ANY_DELTA) {
583 81174dae aliguori
                s->msr &= 0xF0;
584 81174dae aliguori
                serial_update_irq(s);
585 81174dae aliguori
            }
586 80cabfad bellard
        }
587 80cabfad bellard
        break;
588 80cabfad bellard
    case 7:
589 80cabfad bellard
        ret = s->scr;
590 80cabfad bellard
        break;
591 80cabfad bellard
    }
592 b6601141 Michal Novotny
    DPRINTF("read addr=0x%02x val=0x%02x\n", addr, ret);
593 80cabfad bellard
    return ret;
594 80cabfad bellard
}
595 80cabfad bellard
596 82c643ff bellard
static int serial_can_receive(SerialState *s)
597 80cabfad bellard
{
598 81174dae aliguori
    if(s->fcr & UART_FCR_FE) {
599 81174dae aliguori
        if(s->recv_fifo.count < UART_FIFO_LENGTH)
600 81174dae aliguori
        /* Advertise (fifo.itl - fifo.count) bytes when count < ITL, and 1 if above. If UART_FIFO_LENGTH - fifo.count is
601 81174dae aliguori
        advertised the effect will be to almost always fill the fifo completely before the guest has a chance to respond,
602 81174dae aliguori
        effectively overriding the ITL that the guest has set. */
603 81174dae aliguori
             return (s->recv_fifo.count <= s->recv_fifo.itl) ? s->recv_fifo.itl - s->recv_fifo.count : 1;
604 81174dae aliguori
        else
605 81174dae aliguori
             return 0;
606 81174dae aliguori
    } else {
607 80cabfad bellard
    return !(s->lsr & UART_LSR_DR);
608 81174dae aliguori
    }
609 80cabfad bellard
}
610 80cabfad bellard
611 82c643ff bellard
static void serial_receive_break(SerialState *s)
612 80cabfad bellard
{
613 80cabfad bellard
    s->rbr = 0;
614 40ff1624 Jason Wessel
    /* When the LSR_DR is set a null byte is pushed into the fifo */
615 40ff1624 Jason Wessel
    fifo_put(s, RECV_FIFO, '\0');
616 80cabfad bellard
    s->lsr |= UART_LSR_BI | UART_LSR_DR;
617 b41a2cd1 bellard
    serial_update_irq(s);
618 80cabfad bellard
}
619 80cabfad bellard
620 81174dae aliguori
/* There's data in recv_fifo and s->rbr has not been read for 4 char transmit times */
621 81174dae aliguori
static void fifo_timeout_int (void *opaque) {
622 81174dae aliguori
    SerialState *s = opaque;
623 81174dae aliguori
    if (s->recv_fifo.count) {
624 81174dae aliguori
        s->timeout_ipending = 1;
625 81174dae aliguori
        serial_update_irq(s);
626 81174dae aliguori
    }
627 81174dae aliguori
}
628 81174dae aliguori
629 b41a2cd1 bellard
static int serial_can_receive1(void *opaque)
630 80cabfad bellard
{
631 b41a2cd1 bellard
    SerialState *s = opaque;
632 b41a2cd1 bellard
    return serial_can_receive(s);
633 b41a2cd1 bellard
}
634 b41a2cd1 bellard
635 b41a2cd1 bellard
static void serial_receive1(void *opaque, const uint8_t *buf, int size)
636 b41a2cd1 bellard
{
637 b41a2cd1 bellard
    SerialState *s = opaque;
638 81174dae aliguori
    if(s->fcr & UART_FCR_FE) {
639 81174dae aliguori
        int i;
640 81174dae aliguori
        for (i = 0; i < size; i++) {
641 81174dae aliguori
            fifo_put(s, RECV_FIFO, buf[i]);
642 81174dae aliguori
        }
643 81174dae aliguori
        s->lsr |= UART_LSR_DR;
644 81174dae aliguori
        /* call the timeout receive callback in 4 char transmit time */
645 74475455 Paolo Bonzini
        qemu_mod_timer(s->fifo_timeout_timer, qemu_get_clock_ns (vm_clock) + s->char_transmit_time * 4);
646 81174dae aliguori
    } else {
647 71e605f8 Justin T. Gibbs
        if (s->lsr & UART_LSR_DR)
648 71e605f8 Justin T. Gibbs
            s->lsr |= UART_LSR_OE;
649 81174dae aliguori
        s->rbr = buf[0];
650 81174dae aliguori
        s->lsr |= UART_LSR_DR;
651 81174dae aliguori
    }
652 81174dae aliguori
    serial_update_irq(s);
653 b41a2cd1 bellard
}
654 80cabfad bellard
655 82c643ff bellard
static void serial_event(void *opaque, int event)
656 82c643ff bellard
{
657 82c643ff bellard
    SerialState *s = opaque;
658 b6601141 Michal Novotny
    DPRINTF("event %x\n", event);
659 82c643ff bellard
    if (event == CHR_EVENT_BREAK)
660 82c643ff bellard
        serial_receive_break(s);
661 82c643ff bellard
}
662 82c643ff bellard
663 d4bfa4d7 Juan Quintela
static void serial_pre_save(void *opaque)
664 8738a8d0 bellard
{
665 d4bfa4d7 Juan Quintela
    SerialState *s = opaque;
666 747791f1 Juan Quintela
    s->fcr_vmstate = s->fcr;
667 8738a8d0 bellard
}
668 8738a8d0 bellard
669 e59fb374 Juan Quintela
static int serial_post_load(void *opaque, int version_id)
670 747791f1 Juan Quintela
{
671 747791f1 Juan Quintela
    SerialState *s = opaque;
672 81174dae aliguori
673 4c18ce94 Juan Quintela
    if (version_id < 3) {
674 4c18ce94 Juan Quintela
        s->fcr_vmstate = 0;
675 4c18ce94 Juan Quintela
    }
676 81174dae aliguori
    /* Initialize fcr via setter to perform essential side-effects */
677 747791f1 Juan Quintela
    serial_ioport_write(s, 0x02, s->fcr_vmstate);
678 9a7c4878 Michal Novotny
    serial_update_parameters(s);
679 8738a8d0 bellard
    return 0;
680 8738a8d0 bellard
}
681 8738a8d0 bellard
682 747791f1 Juan Quintela
static const VMStateDescription vmstate_serial = {
683 747791f1 Juan Quintela
    .name = "serial",
684 747791f1 Juan Quintela
    .version_id = 3,
685 747791f1 Juan Quintela
    .minimum_version_id = 2,
686 747791f1 Juan Quintela
    .pre_save = serial_pre_save,
687 747791f1 Juan Quintela
    .post_load = serial_post_load,
688 747791f1 Juan Quintela
    .fields      = (VMStateField []) {
689 747791f1 Juan Quintela
        VMSTATE_UINT16_V(divider, SerialState, 2),
690 747791f1 Juan Quintela
        VMSTATE_UINT8(rbr, SerialState),
691 747791f1 Juan Quintela
        VMSTATE_UINT8(ier, SerialState),
692 747791f1 Juan Quintela
        VMSTATE_UINT8(iir, SerialState),
693 747791f1 Juan Quintela
        VMSTATE_UINT8(lcr, SerialState),
694 747791f1 Juan Quintela
        VMSTATE_UINT8(mcr, SerialState),
695 747791f1 Juan Quintela
        VMSTATE_UINT8(lsr, SerialState),
696 747791f1 Juan Quintela
        VMSTATE_UINT8(msr, SerialState),
697 747791f1 Juan Quintela
        VMSTATE_UINT8(scr, SerialState),
698 747791f1 Juan Quintela
        VMSTATE_UINT8_V(fcr_vmstate, SerialState, 3),
699 747791f1 Juan Quintela
        VMSTATE_END_OF_LIST()
700 747791f1 Juan Quintela
    }
701 747791f1 Juan Quintela
};
702 747791f1 Juan Quintela
703 b2a5160c balrog
static void serial_reset(void *opaque)
704 b2a5160c balrog
{
705 b2a5160c balrog
    SerialState *s = opaque;
706 b2a5160c balrog
707 b2a5160c balrog
    s->rbr = 0;
708 b2a5160c balrog
    s->ier = 0;
709 b2a5160c balrog
    s->iir = UART_IIR_NO_INT;
710 b2a5160c balrog
    s->lcr = 0;
711 b2a5160c balrog
    s->lsr = UART_LSR_TEMT | UART_LSR_THRE;
712 b2a5160c balrog
    s->msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS;
713 718b8aec Stefan Weil
    /* Default to 9600 baud, 1 start bit, 8 data bits, 1 stop bit, no parity. */
714 81174dae aliguori
    s->divider = 0x0C;
715 81174dae aliguori
    s->mcr = UART_MCR_OUT2;
716 b2a5160c balrog
    s->scr = 0;
717 81174dae aliguori
    s->tsr_retry = 0;
718 718b8aec Stefan Weil
    s->char_transmit_time = (get_ticks_per_sec() / 9600) * 10;
719 81174dae aliguori
    s->poll_msl = 0;
720 81174dae aliguori
721 81174dae aliguori
    fifo_clear(s,RECV_FIFO);
722 81174dae aliguori
    fifo_clear(s,XMIT_FIFO);
723 81174dae aliguori
724 74475455 Paolo Bonzini
    s->last_xmit_ts = qemu_get_clock_ns(vm_clock);
725 b2a5160c balrog
726 b2a5160c balrog
    s->thr_ipending = 0;
727 b2a5160c balrog
    s->last_break_enable = 0;
728 b2a5160c balrog
    qemu_irq_lower(s->irq);
729 b2a5160c balrog
}
730 b2a5160c balrog
731 ac0be998 Gerd Hoffmann
static void serial_init_core(SerialState *s)
732 81174dae aliguori
{
733 ac0be998 Gerd Hoffmann
    if (!s->chr) {
734 387f4a5a Aurelien Jarno
        fprintf(stderr, "Can't create serial device, empty char device\n");
735 387f4a5a Aurelien Jarno
        exit(1);
736 387f4a5a Aurelien Jarno
    }
737 387f4a5a Aurelien Jarno
738 74475455 Paolo Bonzini
    s->modem_status_poll = qemu_new_timer_ns(vm_clock, (QEMUTimerCB *) serial_update_msl, s);
739 81174dae aliguori
740 74475455 Paolo Bonzini
    s->fifo_timeout_timer = qemu_new_timer_ns(vm_clock, (QEMUTimerCB *) fifo_timeout_int, s);
741 74475455 Paolo Bonzini
    s->transmit_timer = qemu_new_timer_ns(vm_clock, (QEMUTimerCB *) serial_xmit, s);
742 81174dae aliguori
743 a08d4367 Jan Kiszka
    qemu_register_reset(serial_reset, s);
744 81174dae aliguori
745 b47543c4 aurel32
    qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1,
746 b47543c4 aurel32
                          serial_event, s);
747 81174dae aliguori
}
748 81174dae aliguori
749 038eaf82 Stefan Weil
/* Change the main reference oscillator frequency. */
750 038eaf82 Stefan Weil
void serial_set_frequency(SerialState *s, uint32_t frequency)
751 038eaf82 Stefan Weil
{
752 038eaf82 Stefan Weil
    s->baudbase = frequency;
753 038eaf82 Stefan Weil
    serial_update_parameters(s);
754 038eaf82 Stefan Weil
}
755 038eaf82 Stefan Weil
756 e8ee28fb Gerd Hoffmann
static const int isa_serial_io[MAX_SERIAL_PORTS] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
757 e8ee28fb Gerd Hoffmann
static const int isa_serial_irq[MAX_SERIAL_PORTS] = { 4, 3, 4, 3 };
758 e8ee28fb Gerd Hoffmann
759 a941ae45 Richard Henderson
static const MemoryRegionPortio serial_portio[] = {
760 a941ae45 Richard Henderson
    { 0, 8, 1, .read = serial_ioport_read, .write = serial_ioport_write },
761 a941ae45 Richard Henderson
    PORTIO_END_OF_LIST()
762 a941ae45 Richard Henderson
};
763 a941ae45 Richard Henderson
764 a941ae45 Richard Henderson
static const MemoryRegionOps serial_io_ops = {
765 a941ae45 Richard Henderson
    .old_portio = serial_portio
766 a941ae45 Richard Henderson
};
767 a941ae45 Richard Henderson
768 ac0be998 Gerd Hoffmann
static int serial_isa_initfn(ISADevice *dev)
769 ac0be998 Gerd Hoffmann
{
770 e8ee28fb Gerd Hoffmann
    static int index;
771 ac0be998 Gerd Hoffmann
    ISASerialState *isa = DO_UPCAST(ISASerialState, dev, dev);
772 ac0be998 Gerd Hoffmann
    SerialState *s = &isa->state;
773 ac0be998 Gerd Hoffmann
774 e8ee28fb Gerd Hoffmann
    if (isa->index == -1)
775 e8ee28fb Gerd Hoffmann
        isa->index = index;
776 e8ee28fb Gerd Hoffmann
    if (isa->index >= MAX_SERIAL_PORTS)
777 e8ee28fb Gerd Hoffmann
        return -1;
778 e8ee28fb Gerd Hoffmann
    if (isa->iobase == -1)
779 e8ee28fb Gerd Hoffmann
        isa->iobase = isa_serial_io[isa->index];
780 e8ee28fb Gerd Hoffmann
    if (isa->isairq == -1)
781 e8ee28fb Gerd Hoffmann
        isa->isairq = isa_serial_irq[isa->index];
782 e8ee28fb Gerd Hoffmann
    index++;
783 e8ee28fb Gerd Hoffmann
784 ac0be998 Gerd Hoffmann
    s->baudbase = 115200;
785 ac0be998 Gerd Hoffmann
    isa_init_irq(dev, &s->irq, isa->isairq);
786 ac0be998 Gerd Hoffmann
    serial_init_core(s);
787 1cc9f514 Jan Kiszka
    qdev_set_legacy_instance_id(&dev->qdev, isa->iobase, 3);
788 ac0be998 Gerd Hoffmann
789 8e8ffc44 Richard Henderson
    memory_region_init_io(&s->io, &serial_io_ops, s, "serial", 8);
790 8e8ffc44 Richard Henderson
    isa_register_ioport(dev, &s->io, isa->iobase);
791 ac0be998 Gerd Hoffmann
    return 0;
792 ac0be998 Gerd Hoffmann
}
793 ac0be998 Gerd Hoffmann
794 1cc9f514 Jan Kiszka
static const VMStateDescription vmstate_isa_serial = {
795 1cc9f514 Jan Kiszka
    .name = "serial",
796 1cc9f514 Jan Kiszka
    .version_id = 3,
797 1cc9f514 Jan Kiszka
    .minimum_version_id = 2,
798 1cc9f514 Jan Kiszka
    .fields      = (VMStateField []) {
799 1cc9f514 Jan Kiszka
        VMSTATE_STRUCT(state, ISASerialState, 0, vmstate_serial, SerialState),
800 1cc9f514 Jan Kiszka
        VMSTATE_END_OF_LIST()
801 1cc9f514 Jan Kiszka
    }
802 1cc9f514 Jan Kiszka
};
803 1cc9f514 Jan Kiszka
804 b6cd0ea1 aurel32
SerialState *serial_init(int base, qemu_irq irq, int baudbase,
805 b6cd0ea1 aurel32
                         CharDriverState *chr)
806 b41a2cd1 bellard
{
807 b41a2cd1 bellard
    SerialState *s;
808 b41a2cd1 bellard
809 7267c094 Anthony Liguori
    s = g_malloc0(sizeof(SerialState));
810 6936bfe5 aurel32
811 ac0be998 Gerd Hoffmann
    s->irq = irq;
812 ac0be998 Gerd Hoffmann
    s->baudbase = baudbase;
813 ac0be998 Gerd Hoffmann
    s->chr = chr;
814 ac0be998 Gerd Hoffmann
    serial_init_core(s);
815 b41a2cd1 bellard
816 0be71e32 Alex Williamson
    vmstate_register(NULL, base, &vmstate_serial, s);
817 8738a8d0 bellard
818 b41a2cd1 bellard
    register_ioport_write(base, 8, 1, serial_ioport_write, s);
819 b41a2cd1 bellard
    register_ioport_read(base, 8, 1, serial_ioport_read, s);
820 b41a2cd1 bellard
    return s;
821 80cabfad bellard
}
822 e5d13e2f bellard
823 e5d13e2f bellard
/* Memory mapped interface */
824 8e8ffc44 Richard Henderson
static uint64_t serial_mm_read(void *opaque, target_phys_addr_t addr,
825 8e8ffc44 Richard Henderson
                               unsigned size)
826 e5d13e2f bellard
{
827 e5d13e2f bellard
    SerialState *s = opaque;
828 8e8ffc44 Richard Henderson
    return serial_ioport_read(s, addr >> s->it_shift);
829 e5d13e2f bellard
}
830 e5d13e2f bellard
831 8e8ffc44 Richard Henderson
static void serial_mm_write(void *opaque, target_phys_addr_t addr,
832 8e8ffc44 Richard Henderson
                            uint64_t value, unsigned size)
833 2d48377a Blue Swirl
{
834 2d48377a Blue Swirl
    SerialState *s = opaque;
835 8e8ffc44 Richard Henderson
    value &= ~0u >> (32 - (size * 8));
836 2d48377a Blue Swirl
    serial_ioport_write(s, addr >> s->it_shift, value);
837 2d48377a Blue Swirl
}
838 2d48377a Blue Swirl
839 8e8ffc44 Richard Henderson
static const MemoryRegionOps serial_mm_ops[3] = {
840 8e8ffc44 Richard Henderson
    [DEVICE_NATIVE_ENDIAN] = {
841 8e8ffc44 Richard Henderson
        .read = serial_mm_read,
842 8e8ffc44 Richard Henderson
        .write = serial_mm_write,
843 8e8ffc44 Richard Henderson
        .endianness = DEVICE_NATIVE_ENDIAN,
844 8e8ffc44 Richard Henderson
    },
845 8e8ffc44 Richard Henderson
    [DEVICE_LITTLE_ENDIAN] = {
846 8e8ffc44 Richard Henderson
        .read = serial_mm_read,
847 8e8ffc44 Richard Henderson
        .write = serial_mm_write,
848 8e8ffc44 Richard Henderson
        .endianness = DEVICE_LITTLE_ENDIAN,
849 8e8ffc44 Richard Henderson
    },
850 8e8ffc44 Richard Henderson
    [DEVICE_BIG_ENDIAN] = {
851 8e8ffc44 Richard Henderson
        .read = serial_mm_read,
852 8e8ffc44 Richard Henderson
        .write = serial_mm_write,
853 8e8ffc44 Richard Henderson
        .endianness = DEVICE_BIG_ENDIAN,
854 8e8ffc44 Richard Henderson
    },
855 e5d13e2f bellard
};
856 e5d13e2f bellard
857 39186d8a Richard Henderson
SerialState *serial_mm_init(MemoryRegion *address_space,
858 39186d8a Richard Henderson
                            target_phys_addr_t base, int it_shift,
859 39186d8a Richard Henderson
                            qemu_irq irq, int baudbase,
860 39186d8a Richard Henderson
                            CharDriverState *chr, enum device_endian end)
861 e5d13e2f bellard
{
862 e5d13e2f bellard
    SerialState *s;
863 e5d13e2f bellard
864 7267c094 Anthony Liguori
    s = g_malloc0(sizeof(SerialState));
865 81174dae aliguori
866 e5d13e2f bellard
    s->it_shift = it_shift;
867 ac0be998 Gerd Hoffmann
    s->irq = irq;
868 ac0be998 Gerd Hoffmann
    s->baudbase = baudbase;
869 ac0be998 Gerd Hoffmann
    s->chr = chr;
870 e5d13e2f bellard
871 ac0be998 Gerd Hoffmann
    serial_init_core(s);
872 0be71e32 Alex Williamson
    vmstate_register(NULL, base, &vmstate_serial, s);
873 e5d13e2f bellard
874 8e8ffc44 Richard Henderson
    memory_region_init_io(&s->io, &serial_mm_ops[end], s,
875 8e8ffc44 Richard Henderson
                          "serial", 8 << it_shift);
876 39186d8a Richard Henderson
    memory_region_add_subregion(address_space, base, &s->io);
877 2ff0c7c3 Richard Henderson
878 81174dae aliguori
    serial_update_msl(s);
879 e5d13e2f bellard
    return s;
880 e5d13e2f bellard
}
881 ac0be998 Gerd Hoffmann
882 ac0be998 Gerd Hoffmann
static ISADeviceInfo serial_isa_info = {
883 ac0be998 Gerd Hoffmann
    .qdev.name  = "isa-serial",
884 ac0be998 Gerd Hoffmann
    .qdev.size  = sizeof(ISASerialState),
885 1cc9f514 Jan Kiszka
    .qdev.vmsd  = &vmstate_isa_serial,
886 ac0be998 Gerd Hoffmann
    .init       = serial_isa_initfn,
887 ac0be998 Gerd Hoffmann
    .qdev.props = (Property[]) {
888 51954d56 Gerd Hoffmann
        DEFINE_PROP_UINT32("index", ISASerialState, index,   -1),
889 e8ee28fb Gerd Hoffmann
        DEFINE_PROP_HEX32("iobase", ISASerialState, iobase,  -1),
890 e8ee28fb Gerd Hoffmann
        DEFINE_PROP_UINT32("irq",   ISASerialState, isairq,  -1),
891 ac0be998 Gerd Hoffmann
        DEFINE_PROP_CHR("chardev",  ISASerialState, state.chr),
892 ac0be998 Gerd Hoffmann
        DEFINE_PROP_END_OF_LIST(),
893 ac0be998 Gerd Hoffmann
    },
894 ac0be998 Gerd Hoffmann
};
895 ac0be998 Gerd Hoffmann
896 ac0be998 Gerd Hoffmann
static void serial_register_devices(void)
897 ac0be998 Gerd Hoffmann
{
898 ac0be998 Gerd Hoffmann
    isa_qdev_register(&serial_isa_info);
899 ac0be998 Gerd Hoffmann
}
900 ac0be998 Gerd Hoffmann
901 ac0be998 Gerd Hoffmann
device_init(serial_register_devices)