Statistics
| Branch: | Revision:

root / hw / serial.c @ 9e2c1298

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