Statistics
| Branch: | Revision:

root / hw / serial.c @ 9ba2f660

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