Statistics
| Branch: | Revision:

root / hw / serial.c @ 802670e6

History | View | Annotate | Download (24.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 81174dae aliguori
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 81174dae aliguori
} typedef 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 80cabfad bellard
    /* NOTE: this hidden state is necessary for tx irq generation as
123 80cabfad bellard
       it can be reset while reading iir */
124 80cabfad bellard
    int thr_ipending;
125 d537cf6c pbrook
    qemu_irq irq;
126 82c643ff bellard
    CharDriverState *chr;
127 f8d179e3 bellard
    int last_break_enable;
128 e5d13e2f bellard
    int it_shift;
129 b6cd0ea1 aurel32
    int baudbase;
130 81174dae aliguori
    int tsr_retry;
131 81174dae aliguori
132 81174dae aliguori
    uint64_t last_xmit_ts;              /* Time when the last byte was successfully sent out of the tsr */
133 81174dae aliguori
    SerialFIFO recv_fifo;
134 81174dae aliguori
    SerialFIFO xmit_fifo;
135 81174dae aliguori
136 81174dae aliguori
    struct QEMUTimer *fifo_timeout_timer;
137 81174dae aliguori
    int timeout_ipending;                   /* timeout interrupt pending state */
138 81174dae aliguori
    struct QEMUTimer *transmit_timer;
139 81174dae aliguori
140 81174dae aliguori
141 81174dae aliguori
    uint64_t char_transmit_time;               /* time to transmit a char in ticks*/
142 81174dae aliguori
    int poll_msl;
143 81174dae aliguori
144 81174dae aliguori
    struct QEMUTimer *modem_status_poll;
145 b41a2cd1 bellard
};
146 80cabfad bellard
147 81174dae aliguori
static void serial_receive1(void *opaque, const uint8_t *buf, int size);
148 b2a5160c balrog
149 81174dae aliguori
static void fifo_clear(SerialState *s, int fifo)
150 80cabfad bellard
{
151 81174dae aliguori
    SerialFIFO *f = (fifo) ? &s->recv_fifo : &s->xmit_fifo;
152 81174dae aliguori
    memset(f->data, 0, UART_FIFO_LENGTH);
153 81174dae aliguori
    f->count = 0;
154 81174dae aliguori
    f->head = 0;
155 81174dae aliguori
    f->tail = 0;
156 80cabfad bellard
}
157 80cabfad bellard
158 81174dae aliguori
static int fifo_put(SerialState *s, int fifo, uint8_t chr)
159 6936bfe5 aurel32
{
160 81174dae aliguori
    SerialFIFO *f = (fifo) ? &s->recv_fifo : &s->xmit_fifo;
161 6936bfe5 aurel32
162 81174dae aliguori
    f->data[f->head++] = chr;
163 6936bfe5 aurel32
164 81174dae aliguori
    if (f->head == UART_FIFO_LENGTH)
165 81174dae aliguori
        f->head = 0;
166 81174dae aliguori
    f->count++;
167 81174dae aliguori
168 81174dae aliguori
    return 1;
169 81174dae aliguori
}
170 81174dae aliguori
171 81174dae aliguori
static uint8_t fifo_get(SerialState *s, int fifo)
172 81174dae aliguori
{
173 81174dae aliguori
    SerialFIFO *f = (fifo) ? &s->recv_fifo : &s->xmit_fifo;
174 81174dae aliguori
    uint8_t c;
175 81174dae aliguori
176 81174dae aliguori
    if(f->count == 0)
177 81174dae aliguori
        return 0;
178 81174dae aliguori
179 81174dae aliguori
    c = f->data[f->tail++];
180 81174dae aliguori
    if (f->tail == UART_FIFO_LENGTH)
181 81174dae aliguori
        f->tail = 0;
182 81174dae aliguori
    f->count--;
183 81174dae aliguori
184 81174dae aliguori
    return c;
185 81174dae aliguori
}
186 6936bfe5 aurel32
187 81174dae aliguori
static void serial_update_irq(SerialState *s)
188 81174dae aliguori
{
189 81174dae aliguori
    uint8_t tmp_iir = UART_IIR_NO_INT;
190 81174dae aliguori
191 81174dae aliguori
    if ((s->ier & UART_IER_RLSI) && (s->lsr & UART_LSR_INT_ANY)) {
192 81174dae aliguori
        tmp_iir = UART_IIR_RLSI;
193 5628a626 balrog
    } else if ((s->ier & UART_IER_RDI) && s->timeout_ipending) {
194 c9a33054 balrog
        /* Note that(s->ier & UART_IER_RDI) can mask this interrupt,
195 c9a33054 balrog
         * this is not in the specification but is observed on existing
196 c9a33054 balrog
         * hardware.  */
197 81174dae aliguori
        tmp_iir = UART_IIR_CTI;
198 81174dae aliguori
    } else if ((s->ier & UART_IER_RDI) && (s->lsr & UART_LSR_DR)) {
199 81174dae aliguori
        if (!(s->fcr & UART_FCR_FE)) {
200 81174dae aliguori
           tmp_iir = UART_IIR_RDI;
201 81174dae aliguori
        } else if (s->recv_fifo.count >= s->recv_fifo.itl) {
202 81174dae aliguori
           tmp_iir = UART_IIR_RDI;
203 81174dae aliguori
        }
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 81174dae aliguori
    s->char_transmit_time =  (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 81174dae aliguori
        qemu_mod_timer(s->modem_status_poll, qemu_get_clock(vm_clock) + 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 8738a8d0 bellard
static void serial_save(QEMUFile *f, void *opaque)
639 8738a8d0 bellard
{
640 8738a8d0 bellard
    SerialState *s = opaque;
641 8738a8d0 bellard
642 508d92d0 bellard
    qemu_put_be16s(f,&s->divider);
643 8738a8d0 bellard
    qemu_put_8s(f,&s->rbr);
644 8738a8d0 bellard
    qemu_put_8s(f,&s->ier);
645 8738a8d0 bellard
    qemu_put_8s(f,&s->iir);
646 8738a8d0 bellard
    qemu_put_8s(f,&s->lcr);
647 8738a8d0 bellard
    qemu_put_8s(f,&s->mcr);
648 8738a8d0 bellard
    qemu_put_8s(f,&s->lsr);
649 8738a8d0 bellard
    qemu_put_8s(f,&s->msr);
650 8738a8d0 bellard
    qemu_put_8s(f,&s->scr);
651 81174dae aliguori
    qemu_put_8s(f,&s->fcr);
652 8738a8d0 bellard
}
653 8738a8d0 bellard
654 8738a8d0 bellard
static int serial_load(QEMUFile *f, void *opaque, int version_id)
655 8738a8d0 bellard
{
656 8738a8d0 bellard
    SerialState *s = opaque;
657 81174dae aliguori
    uint8_t fcr = 0;
658 8738a8d0 bellard
659 81174dae aliguori
    if(version_id > 3)
660 8738a8d0 bellard
        return -EINVAL;
661 8738a8d0 bellard
662 508d92d0 bellard
    if (version_id >= 2)
663 508d92d0 bellard
        qemu_get_be16s(f, &s->divider);
664 508d92d0 bellard
    else
665 508d92d0 bellard
        s->divider = qemu_get_byte(f);
666 8738a8d0 bellard
    qemu_get_8s(f,&s->rbr);
667 8738a8d0 bellard
    qemu_get_8s(f,&s->ier);
668 8738a8d0 bellard
    qemu_get_8s(f,&s->iir);
669 8738a8d0 bellard
    qemu_get_8s(f,&s->lcr);
670 8738a8d0 bellard
    qemu_get_8s(f,&s->mcr);
671 8738a8d0 bellard
    qemu_get_8s(f,&s->lsr);
672 8738a8d0 bellard
    qemu_get_8s(f,&s->msr);
673 8738a8d0 bellard
    qemu_get_8s(f,&s->scr);
674 8738a8d0 bellard
675 81174dae aliguori
    if (version_id >= 3)
676 81174dae aliguori
        qemu_get_8s(f,&fcr);
677 81174dae aliguori
678 81174dae aliguori
    /* Initialize fcr via setter to perform essential side-effects */
679 81174dae aliguori
    serial_ioport_write(s, 0x02, fcr);
680 8738a8d0 bellard
    return 0;
681 8738a8d0 bellard
}
682 8738a8d0 bellard
683 b2a5160c balrog
static void serial_reset(void *opaque)
684 b2a5160c balrog
{
685 b2a5160c balrog
    SerialState *s = opaque;
686 b2a5160c balrog
687 b2a5160c balrog
    s->rbr = 0;
688 b2a5160c balrog
    s->ier = 0;
689 b2a5160c balrog
    s->iir = UART_IIR_NO_INT;
690 b2a5160c balrog
    s->lcr = 0;
691 b2a5160c balrog
    s->lsr = UART_LSR_TEMT | UART_LSR_THRE;
692 b2a5160c balrog
    s->msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS;
693 81174dae aliguori
    /* Default to 9600 baud, no parity, one stop bit */
694 81174dae aliguori
    s->divider = 0x0C;
695 81174dae aliguori
    s->mcr = UART_MCR_OUT2;
696 b2a5160c balrog
    s->scr = 0;
697 81174dae aliguori
    s->tsr_retry = 0;
698 81174dae aliguori
    s->char_transmit_time = (ticks_per_sec / 9600) * 9;
699 81174dae aliguori
    s->poll_msl = 0;
700 81174dae aliguori
701 81174dae aliguori
    fifo_clear(s,RECV_FIFO);
702 81174dae aliguori
    fifo_clear(s,XMIT_FIFO);
703 81174dae aliguori
704 81174dae aliguori
    s->last_xmit_ts = qemu_get_clock(vm_clock);
705 b2a5160c balrog
706 b2a5160c balrog
    s->thr_ipending = 0;
707 b2a5160c balrog
    s->last_break_enable = 0;
708 b2a5160c balrog
    qemu_irq_lower(s->irq);
709 b2a5160c balrog
}
710 b2a5160c balrog
711 81174dae aliguori
static void serial_init_core(SerialState *s, qemu_irq irq, int baudbase,
712 81174dae aliguori
                             CharDriverState *chr)
713 81174dae aliguori
{
714 81174dae aliguori
    s->irq = irq;
715 81174dae aliguori
    s->baudbase = baudbase;
716 b47543c4 aurel32
    s->chr = chr ?: qemu_chr_open("null", "null", NULL);
717 81174dae aliguori
718 81174dae aliguori
    s->modem_status_poll = qemu_new_timer(vm_clock, (QEMUTimerCB *) serial_update_msl, s);
719 81174dae aliguori
720 81174dae aliguori
    s->fifo_timeout_timer = qemu_new_timer(vm_clock, (QEMUTimerCB *) fifo_timeout_int, s);
721 81174dae aliguori
    s->transmit_timer = qemu_new_timer(vm_clock, (QEMUTimerCB *) serial_xmit, s);
722 81174dae aliguori
723 a08d4367 Jan Kiszka
    qemu_register_reset(serial_reset, s);
724 81174dae aliguori
    serial_reset(s);
725 81174dae aliguori
726 b47543c4 aurel32
    qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1,
727 b47543c4 aurel32
                          serial_event, s);
728 81174dae aliguori
}
729 81174dae aliguori
730 b41a2cd1 bellard
/* If fd is zero, it means that the serial device uses the console */
731 b6cd0ea1 aurel32
SerialState *serial_init(int base, qemu_irq irq, int baudbase,
732 b6cd0ea1 aurel32
                         CharDriverState *chr)
733 b41a2cd1 bellard
{
734 b41a2cd1 bellard
    SerialState *s;
735 b41a2cd1 bellard
736 b41a2cd1 bellard
    s = qemu_mallocz(sizeof(SerialState));
737 6936bfe5 aurel32
738 81174dae aliguori
    serial_init_core(s, irq, baudbase, chr);
739 b41a2cd1 bellard
740 81174dae aliguori
    register_savevm("serial", base, 3, serial_save, serial_load, s);
741 8738a8d0 bellard
742 b41a2cd1 bellard
    register_ioport_write(base, 8, 1, serial_ioport_write, s);
743 b41a2cd1 bellard
    register_ioport_read(base, 8, 1, serial_ioport_read, s);
744 b41a2cd1 bellard
    return s;
745 80cabfad bellard
}
746 e5d13e2f bellard
747 e5d13e2f bellard
/* Memory mapped interface */
748 802670e6 Blue Swirl
static uint32_t serial_mm_readb(void *opaque, target_phys_addr_t addr)
749 e5d13e2f bellard
{
750 e5d13e2f bellard
    SerialState *s = opaque;
751 e5d13e2f bellard
752 8da3ff18 pbrook
    return serial_ioport_read(s, addr >> s->it_shift) & 0xFF;
753 e5d13e2f bellard
}
754 e5d13e2f bellard
755 802670e6 Blue Swirl
static void serial_mm_writeb(void *opaque, target_phys_addr_t addr,
756 802670e6 Blue Swirl
                             uint32_t value)
757 e5d13e2f bellard
{
758 e5d13e2f bellard
    SerialState *s = opaque;
759 e5d13e2f bellard
760 8da3ff18 pbrook
    serial_ioport_write(s, addr >> s->it_shift, value & 0xFF);
761 e5d13e2f bellard
}
762 e5d13e2f bellard
763 802670e6 Blue Swirl
static uint32_t serial_mm_readw(void *opaque, target_phys_addr_t addr)
764 e5d13e2f bellard
{
765 e5d13e2f bellard
    SerialState *s = opaque;
766 e918ee04 ths
    uint32_t val;
767 e5d13e2f bellard
768 8da3ff18 pbrook
    val = serial_ioport_read(s, addr >> s->it_shift) & 0xFFFF;
769 e918ee04 ths
#ifdef TARGET_WORDS_BIGENDIAN
770 e918ee04 ths
    val = bswap16(val);
771 e918ee04 ths
#endif
772 e918ee04 ths
    return val;
773 e5d13e2f bellard
}
774 e5d13e2f bellard
775 802670e6 Blue Swirl
static void serial_mm_writew(void *opaque, target_phys_addr_t addr,
776 802670e6 Blue Swirl
                             uint32_t value)
777 e5d13e2f bellard
{
778 e5d13e2f bellard
    SerialState *s = opaque;
779 e918ee04 ths
#ifdef TARGET_WORDS_BIGENDIAN
780 e918ee04 ths
    value = bswap16(value);
781 e918ee04 ths
#endif
782 8da3ff18 pbrook
    serial_ioport_write(s, addr >> s->it_shift, value & 0xFFFF);
783 e5d13e2f bellard
}
784 e5d13e2f bellard
785 802670e6 Blue Swirl
static uint32_t serial_mm_readl(void *opaque, target_phys_addr_t addr)
786 e5d13e2f bellard
{
787 e5d13e2f bellard
    SerialState *s = opaque;
788 e918ee04 ths
    uint32_t val;
789 e5d13e2f bellard
790 8da3ff18 pbrook
    val = serial_ioport_read(s, addr >> s->it_shift);
791 e918ee04 ths
#ifdef TARGET_WORDS_BIGENDIAN
792 e918ee04 ths
    val = bswap32(val);
793 e918ee04 ths
#endif
794 e918ee04 ths
    return val;
795 e5d13e2f bellard
}
796 e5d13e2f bellard
797 802670e6 Blue Swirl
static void serial_mm_writel(void *opaque, target_phys_addr_t addr,
798 802670e6 Blue Swirl
                             uint32_t value)
799 e5d13e2f bellard
{
800 e5d13e2f bellard
    SerialState *s = opaque;
801 e918ee04 ths
#ifdef TARGET_WORDS_BIGENDIAN
802 e918ee04 ths
    value = bswap32(value);
803 e918ee04 ths
#endif
804 8da3ff18 pbrook
    serial_ioport_write(s, addr >> s->it_shift, value);
805 e5d13e2f bellard
}
806 e5d13e2f bellard
807 e5d13e2f bellard
static CPUReadMemoryFunc *serial_mm_read[] = {
808 e5d13e2f bellard
    &serial_mm_readb,
809 e5d13e2f bellard
    &serial_mm_readw,
810 e5d13e2f bellard
    &serial_mm_readl,
811 e5d13e2f bellard
};
812 e5d13e2f bellard
813 e5d13e2f bellard
static CPUWriteMemoryFunc *serial_mm_write[] = {
814 e5d13e2f bellard
    &serial_mm_writeb,
815 e5d13e2f bellard
    &serial_mm_writew,
816 e5d13e2f bellard
    &serial_mm_writel,
817 e5d13e2f bellard
};
818 e5d13e2f bellard
819 71db710f blueswir1
SerialState *serial_mm_init (target_phys_addr_t base, int it_shift,
820 b6cd0ea1 aurel32
                             qemu_irq irq, int baudbase,
821 b6cd0ea1 aurel32
                             CharDriverState *chr, int ioregister)
822 e5d13e2f bellard
{
823 e5d13e2f bellard
    SerialState *s;
824 e5d13e2f bellard
    int s_io_memory;
825 e5d13e2f bellard
826 e5d13e2f bellard
    s = qemu_mallocz(sizeof(SerialState));
827 81174dae aliguori
828 e5d13e2f bellard
    s->it_shift = it_shift;
829 e5d13e2f bellard
830 81174dae aliguori
    serial_init_core(s, irq, baudbase, chr);
831 81174dae aliguori
    register_savevm("serial", base, 3, serial_save, serial_load, s);
832 e5d13e2f bellard
833 a4bc3afc ths
    if (ioregister) {
834 1eed09cb Avi Kivity
        s_io_memory = cpu_register_io_memory(serial_mm_read,
835 a4bc3afc ths
                                             serial_mm_write, s);
836 a4bc3afc ths
        cpu_register_physical_memory(base, 8 << it_shift, s_io_memory);
837 a4bc3afc ths
    }
838 81174dae aliguori
    serial_update_msl(s);
839 e5d13e2f bellard
    return s;
840 e5d13e2f bellard
}