Statistics
| Branch: | Revision:

root / hw / serial.c @ c79ce737

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