Statistics
| Branch: | Revision:

root / hw / serial.c @ a74cdab4

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