Statistics
| Branch: | Revision:

root / hw / serial.c @ 99a0949b

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