Statistics
| Branch: | Revision:

root / hw / serial.c @ 2cae4119

History | View | Annotate | Download (27.5 kB)

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