Statistics
| Branch: | Revision:

root / hw / serial.c @ 6450a334

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