Statistics
| Branch: | Revision:

root / hw / serial.c @ c9f398e5

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