Statistics
| Branch: | Revision:

root / hw / serial.c @ 7830cf78

History | View | Annotate | Download (23.4 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 927d4878 Paolo Bonzini
#include "char/char.h"
28 1de7afc9 Paolo Bonzini
#include "qemu/timer.h"
29 022c62cb Paolo Bonzini
#include "exec/address-spaces.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 fcfb4d6a Anthony Liguori
static gboolean serial_xmit(GIOChannel *chan, GIOCondition cond, void *opaque)
260 81174dae aliguori
{
261 81174dae aliguori
    SerialState *s = opaque;
262 81174dae aliguori
263 81174dae aliguori
    if (s->tsr_retry <= 0) {
264 81174dae aliguori
        if (s->fcr & UART_FCR_FE) {
265 81174dae aliguori
            s->tsr = fifo_get(s,XMIT_FIFO);
266 81174dae aliguori
            if (!s->xmit_fifo.count)
267 81174dae aliguori
                s->lsr |= UART_LSR_THRE;
268 fcfb4d6a Anthony Liguori
        } else if ((s->lsr & UART_LSR_THRE)) {
269 fcfb4d6a Anthony Liguori
            return FALSE;
270 81174dae aliguori
        } else {
271 81174dae aliguori
            s->tsr = s->thr;
272 81174dae aliguori
            s->lsr |= UART_LSR_THRE;
273 dfe844c9 Anthony Liguori
            s->lsr &= ~UART_LSR_TEMT;
274 81174dae aliguori
        }
275 81174dae aliguori
    }
276 81174dae aliguori
277 81174dae aliguori
    if (s->mcr & UART_MCR_LOOP) {
278 81174dae aliguori
        /* in loopback mode, say that we just received a char */
279 81174dae aliguori
        serial_receive1(s, &s->tsr, 1);
280 2cc6e0a1 Anthony Liguori
    } else if (qemu_chr_fe_write(s->chr, &s->tsr, 1) != 1) {
281 fcfb4d6a Anthony Liguori
        if (s->tsr_retry >= 0 && s->tsr_retry < MAX_XMIT_RETRY &&
282 fcfb4d6a Anthony Liguori
            qemu_chr_fe_add_watch(s->chr, G_IO_OUT, serial_xmit, s) > 0) {
283 81174dae aliguori
            s->tsr_retry++;
284 fcfb4d6a Anthony Liguori
            return FALSE;
285 81174dae aliguori
        }
286 fcfb4d6a Anthony Liguori
        s->tsr_retry = 0;
287 fcfb4d6a Anthony Liguori
    } else {
288 81174dae aliguori
        s->tsr_retry = 0;
289 81174dae aliguori
    }
290 81174dae aliguori
291 74475455 Paolo Bonzini
    s->last_xmit_ts = qemu_get_clock_ns(vm_clock);
292 81174dae aliguori
293 81174dae aliguori
    if (s->lsr & UART_LSR_THRE) {
294 81174dae aliguori
        s->lsr |= UART_LSR_TEMT;
295 81174dae aliguori
        s->thr_ipending = 1;
296 81174dae aliguori
        serial_update_irq(s);
297 81174dae aliguori
    }
298 fcfb4d6a Anthony Liguori
299 fcfb4d6a Anthony Liguori
    return FALSE;
300 81174dae aliguori
}
301 81174dae aliguori
302 81174dae aliguori
303 5ec3a23e Alexander Graf
static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val,
304 5ec3a23e Alexander Graf
                                unsigned size)
305 80cabfad bellard
{
306 b41a2cd1 bellard
    SerialState *s = opaque;
307 3b46e624 ths
308 80cabfad bellard
    addr &= 7;
309 b6601141 Michal Novotny
    DPRINTF("write addr=0x%02x val=0x%02x\n", addr, val);
310 80cabfad bellard
    switch(addr) {
311 80cabfad bellard
    default:
312 80cabfad bellard
    case 0:
313 80cabfad bellard
        if (s->lcr & UART_LCR_DLAB) {
314 80cabfad bellard
            s->divider = (s->divider & 0xff00) | val;
315 f8d179e3 bellard
            serial_update_parameters(s);
316 80cabfad bellard
        } else {
317 81174dae aliguori
            s->thr = (uint8_t) val;
318 81174dae aliguori
            if(s->fcr & UART_FCR_FE) {
319 2f4f22bd Aurelien Jarno
                fifo_put(s, XMIT_FIFO, s->thr);
320 2f4f22bd Aurelien Jarno
                s->thr_ipending = 0;
321 2f4f22bd Aurelien Jarno
                s->lsr &= ~UART_LSR_TEMT;
322 2f4f22bd Aurelien Jarno
                s->lsr &= ~UART_LSR_THRE;
323 2f4f22bd Aurelien Jarno
                serial_update_irq(s);
324 6936bfe5 aurel32
            } else {
325 2f4f22bd Aurelien Jarno
                s->thr_ipending = 0;
326 2f4f22bd Aurelien Jarno
                s->lsr &= ~UART_LSR_THRE;
327 2f4f22bd Aurelien Jarno
                serial_update_irq(s);
328 6936bfe5 aurel32
            }
329 fcfb4d6a Anthony Liguori
            serial_xmit(NULL, G_IO_OUT, s);
330 80cabfad bellard
        }
331 80cabfad bellard
        break;
332 80cabfad bellard
    case 1:
333 80cabfad bellard
        if (s->lcr & UART_LCR_DLAB) {
334 80cabfad bellard
            s->divider = (s->divider & 0x00ff) | (val << 8);
335 f8d179e3 bellard
            serial_update_parameters(s);
336 80cabfad bellard
        } else {
337 60e336db bellard
            s->ier = val & 0x0f;
338 81174dae aliguori
            /* If the backend device is a real serial port, turn polling of the modem
339 81174dae aliguori
               status lines on physical port on or off depending on UART_IER_MSI state */
340 81174dae aliguori
            if (s->poll_msl >= 0) {
341 81174dae aliguori
                if (s->ier & UART_IER_MSI) {
342 81174dae aliguori
                     s->poll_msl = 1;
343 81174dae aliguori
                     serial_update_msl(s);
344 81174dae aliguori
                } else {
345 81174dae aliguori
                     qemu_del_timer(s->modem_status_poll);
346 81174dae aliguori
                     s->poll_msl = 0;
347 81174dae aliguori
                }
348 81174dae aliguori
            }
349 60e336db bellard
            if (s->lsr & UART_LSR_THRE) {
350 60e336db bellard
                s->thr_ipending = 1;
351 81174dae aliguori
                serial_update_irq(s);
352 60e336db bellard
            }
353 80cabfad bellard
        }
354 80cabfad bellard
        break;
355 80cabfad bellard
    case 2:
356 81174dae aliguori
        val = val & 0xFF;
357 81174dae aliguori
358 81174dae aliguori
        if (s->fcr == val)
359 81174dae aliguori
            break;
360 81174dae aliguori
361 81174dae aliguori
        /* Did the enable/disable flag change? If so, make sure FIFOs get flushed */
362 81174dae aliguori
        if ((val ^ s->fcr) & UART_FCR_FE)
363 81174dae aliguori
            val |= UART_FCR_XFR | UART_FCR_RFR;
364 81174dae aliguori
365 81174dae aliguori
        /* FIFO clear */
366 81174dae aliguori
367 81174dae aliguori
        if (val & UART_FCR_RFR) {
368 81174dae aliguori
            qemu_del_timer(s->fifo_timeout_timer);
369 81174dae aliguori
            s->timeout_ipending=0;
370 81174dae aliguori
            fifo_clear(s,RECV_FIFO);
371 81174dae aliguori
        }
372 81174dae aliguori
373 81174dae aliguori
        if (val & UART_FCR_XFR) {
374 81174dae aliguori
            fifo_clear(s,XMIT_FIFO);
375 81174dae aliguori
        }
376 81174dae aliguori
377 81174dae aliguori
        if (val & UART_FCR_FE) {
378 81174dae aliguori
            s->iir |= UART_IIR_FE;
379 81174dae aliguori
            /* Set RECV_FIFO trigger Level */
380 81174dae aliguori
            switch (val & 0xC0) {
381 81174dae aliguori
            case UART_FCR_ITL_1:
382 81174dae aliguori
                s->recv_fifo.itl = 1;
383 81174dae aliguori
                break;
384 81174dae aliguori
            case UART_FCR_ITL_2:
385 81174dae aliguori
                s->recv_fifo.itl = 4;
386 81174dae aliguori
                break;
387 81174dae aliguori
            case UART_FCR_ITL_3:
388 81174dae aliguori
                s->recv_fifo.itl = 8;
389 81174dae aliguori
                break;
390 81174dae aliguori
            case UART_FCR_ITL_4:
391 81174dae aliguori
                s->recv_fifo.itl = 14;
392 81174dae aliguori
                break;
393 81174dae aliguori
            }
394 81174dae aliguori
        } else
395 81174dae aliguori
            s->iir &= ~UART_IIR_FE;
396 81174dae aliguori
397 81174dae aliguori
        /* Set fcr - or at least the bits in it that are supposed to "stick" */
398 81174dae aliguori
        s->fcr = val & 0xC9;
399 81174dae aliguori
        serial_update_irq(s);
400 80cabfad bellard
        break;
401 80cabfad bellard
    case 3:
402 f8d179e3 bellard
        {
403 f8d179e3 bellard
            int break_enable;
404 f8d179e3 bellard
            s->lcr = val;
405 f8d179e3 bellard
            serial_update_parameters(s);
406 f8d179e3 bellard
            break_enable = (val >> 6) & 1;
407 f8d179e3 bellard
            if (break_enable != s->last_break_enable) {
408 f8d179e3 bellard
                s->last_break_enable = break_enable;
409 41084f1b Anthony Liguori
                qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
410 2122c51a bellard
                               &break_enable);
411 f8d179e3 bellard
            }
412 f8d179e3 bellard
        }
413 80cabfad bellard
        break;
414 80cabfad bellard
    case 4:
415 81174dae aliguori
        {
416 81174dae aliguori
            int flags;
417 81174dae aliguori
            int old_mcr = s->mcr;
418 81174dae aliguori
            s->mcr = val & 0x1f;
419 81174dae aliguori
            if (val & UART_MCR_LOOP)
420 81174dae aliguori
                break;
421 81174dae aliguori
422 81174dae aliguori
            if (s->poll_msl >= 0 && old_mcr != s->mcr) {
423 81174dae aliguori
424 41084f1b Anthony Liguori
                qemu_chr_fe_ioctl(s->chr,CHR_IOCTL_SERIAL_GET_TIOCM, &flags);
425 81174dae aliguori
426 81174dae aliguori
                flags &= ~(CHR_TIOCM_RTS | CHR_TIOCM_DTR);
427 81174dae aliguori
428 81174dae aliguori
                if (val & UART_MCR_RTS)
429 81174dae aliguori
                    flags |= CHR_TIOCM_RTS;
430 81174dae aliguori
                if (val & UART_MCR_DTR)
431 81174dae aliguori
                    flags |= CHR_TIOCM_DTR;
432 81174dae aliguori
433 41084f1b Anthony Liguori
                qemu_chr_fe_ioctl(s->chr,CHR_IOCTL_SERIAL_SET_TIOCM, &flags);
434 81174dae aliguori
                /* Update the modem status after a one-character-send wait-time, since there may be a response
435 81174dae aliguori
                   from the device/computer at the other end of the serial line */
436 74475455 Paolo Bonzini
                qemu_mod_timer(s->modem_status_poll, qemu_get_clock_ns(vm_clock) + s->char_transmit_time);
437 81174dae aliguori
            }
438 81174dae aliguori
        }
439 80cabfad bellard
        break;
440 80cabfad bellard
    case 5:
441 80cabfad bellard
        break;
442 80cabfad bellard
    case 6:
443 80cabfad bellard
        break;
444 80cabfad bellard
    case 7:
445 80cabfad bellard
        s->scr = val;
446 80cabfad bellard
        break;
447 80cabfad bellard
    }
448 80cabfad bellard
}
449 80cabfad bellard
450 5ec3a23e Alexander Graf
static uint64_t serial_ioport_read(void *opaque, hwaddr addr, unsigned size)
451 80cabfad bellard
{
452 b41a2cd1 bellard
    SerialState *s = opaque;
453 80cabfad bellard
    uint32_t ret;
454 80cabfad bellard
455 80cabfad bellard
    addr &= 7;
456 80cabfad bellard
    switch(addr) {
457 80cabfad bellard
    default:
458 80cabfad bellard
    case 0:
459 80cabfad bellard
        if (s->lcr & UART_LCR_DLAB) {
460 5fafdf24 ths
            ret = s->divider & 0xff;
461 80cabfad bellard
        } else {
462 81174dae aliguori
            if(s->fcr & UART_FCR_FE) {
463 81174dae aliguori
                ret = fifo_get(s,RECV_FIFO);
464 81174dae aliguori
                if (s->recv_fifo.count == 0)
465 81174dae aliguori
                    s->lsr &= ~(UART_LSR_DR | UART_LSR_BI);
466 81174dae aliguori
                else
467 74475455 Paolo Bonzini
                    qemu_mod_timer(s->fifo_timeout_timer, qemu_get_clock_ns (vm_clock) + s->char_transmit_time * 4);
468 81174dae aliguori
                s->timeout_ipending = 0;
469 81174dae aliguori
            } else {
470 81174dae aliguori
                ret = s->rbr;
471 81174dae aliguori
                s->lsr &= ~(UART_LSR_DR | UART_LSR_BI);
472 81174dae aliguori
            }
473 b41a2cd1 bellard
            serial_update_irq(s);
474 b2a5160c balrog
            if (!(s->mcr & UART_MCR_LOOP)) {
475 b2a5160c balrog
                /* in loopback mode, don't receive any data */
476 b2a5160c balrog
                qemu_chr_accept_input(s->chr);
477 b2a5160c balrog
            }
478 80cabfad bellard
        }
479 80cabfad bellard
        break;
480 80cabfad bellard
    case 1:
481 80cabfad bellard
        if (s->lcr & UART_LCR_DLAB) {
482 80cabfad bellard
            ret = (s->divider >> 8) & 0xff;
483 80cabfad bellard
        } else {
484 80cabfad bellard
            ret = s->ier;
485 80cabfad bellard
        }
486 80cabfad bellard
        break;
487 80cabfad bellard
    case 2:
488 80cabfad bellard
        ret = s->iir;
489 cdee7bdf Aurelien Jarno
        if ((ret & UART_IIR_ID) == UART_IIR_THRI) {
490 80cabfad bellard
            s->thr_ipending = 0;
491 71e605f8 Justin T. Gibbs
            serial_update_irq(s);
492 71e605f8 Justin T. Gibbs
        }
493 80cabfad bellard
        break;
494 80cabfad bellard
    case 3:
495 80cabfad bellard
        ret = s->lcr;
496 80cabfad bellard
        break;
497 80cabfad bellard
    case 4:
498 80cabfad bellard
        ret = s->mcr;
499 80cabfad bellard
        break;
500 80cabfad bellard
    case 5:
501 80cabfad bellard
        ret = s->lsr;
502 71e605f8 Justin T. Gibbs
        /* Clear break and overrun interrupts */
503 71e605f8 Justin T. Gibbs
        if (s->lsr & (UART_LSR_BI|UART_LSR_OE)) {
504 71e605f8 Justin T. Gibbs
            s->lsr &= ~(UART_LSR_BI|UART_LSR_OE);
505 81174dae aliguori
            serial_update_irq(s);
506 81174dae aliguori
        }
507 80cabfad bellard
        break;
508 80cabfad bellard
    case 6:
509 80cabfad bellard
        if (s->mcr & UART_MCR_LOOP) {
510 80cabfad bellard
            /* in loopback, the modem output pins are connected to the
511 80cabfad bellard
               inputs */
512 80cabfad bellard
            ret = (s->mcr & 0x0c) << 4;
513 80cabfad bellard
            ret |= (s->mcr & 0x02) << 3;
514 80cabfad bellard
            ret |= (s->mcr & 0x01) << 5;
515 80cabfad bellard
        } else {
516 81174dae aliguori
            if (s->poll_msl >= 0)
517 81174dae aliguori
                serial_update_msl(s);
518 80cabfad bellard
            ret = s->msr;
519 81174dae aliguori
            /* Clear delta bits & msr int after read, if they were set */
520 81174dae aliguori
            if (s->msr & UART_MSR_ANY_DELTA) {
521 81174dae aliguori
                s->msr &= 0xF0;
522 81174dae aliguori
                serial_update_irq(s);
523 81174dae aliguori
            }
524 80cabfad bellard
        }
525 80cabfad bellard
        break;
526 80cabfad bellard
    case 7:
527 80cabfad bellard
        ret = s->scr;
528 80cabfad bellard
        break;
529 80cabfad bellard
    }
530 b6601141 Michal Novotny
    DPRINTF("read addr=0x%02x val=0x%02x\n", addr, ret);
531 80cabfad bellard
    return ret;
532 80cabfad bellard
}
533 80cabfad bellard
534 82c643ff bellard
static int serial_can_receive(SerialState *s)
535 80cabfad bellard
{
536 81174dae aliguori
    if(s->fcr & UART_FCR_FE) {
537 81174dae aliguori
        if(s->recv_fifo.count < UART_FIFO_LENGTH)
538 81174dae aliguori
        /* Advertise (fifo.itl - fifo.count) bytes when count < ITL, and 1 if above. If UART_FIFO_LENGTH - fifo.count is
539 81174dae aliguori
        advertised the effect will be to almost always fill the fifo completely before the guest has a chance to respond,
540 81174dae aliguori
        effectively overriding the ITL that the guest has set. */
541 81174dae aliguori
             return (s->recv_fifo.count <= s->recv_fifo.itl) ? s->recv_fifo.itl - s->recv_fifo.count : 1;
542 81174dae aliguori
        else
543 81174dae aliguori
             return 0;
544 81174dae aliguori
    } else {
545 80cabfad bellard
    return !(s->lsr & UART_LSR_DR);
546 81174dae aliguori
    }
547 80cabfad bellard
}
548 80cabfad bellard
549 82c643ff bellard
static void serial_receive_break(SerialState *s)
550 80cabfad bellard
{
551 80cabfad bellard
    s->rbr = 0;
552 40ff1624 Jason Wessel
    /* When the LSR_DR is set a null byte is pushed into the fifo */
553 40ff1624 Jason Wessel
    fifo_put(s, RECV_FIFO, '\0');
554 80cabfad bellard
    s->lsr |= UART_LSR_BI | UART_LSR_DR;
555 b41a2cd1 bellard
    serial_update_irq(s);
556 80cabfad bellard
}
557 80cabfad bellard
558 81174dae aliguori
/* There's data in recv_fifo and s->rbr has not been read for 4 char transmit times */
559 81174dae aliguori
static void fifo_timeout_int (void *opaque) {
560 81174dae aliguori
    SerialState *s = opaque;
561 81174dae aliguori
    if (s->recv_fifo.count) {
562 81174dae aliguori
        s->timeout_ipending = 1;
563 81174dae aliguori
        serial_update_irq(s);
564 81174dae aliguori
    }
565 81174dae aliguori
}
566 81174dae aliguori
567 b41a2cd1 bellard
static int serial_can_receive1(void *opaque)
568 80cabfad bellard
{
569 b41a2cd1 bellard
    SerialState *s = opaque;
570 b41a2cd1 bellard
    return serial_can_receive(s);
571 b41a2cd1 bellard
}
572 b41a2cd1 bellard
573 b41a2cd1 bellard
static void serial_receive1(void *opaque, const uint8_t *buf, int size)
574 b41a2cd1 bellard
{
575 b41a2cd1 bellard
    SerialState *s = opaque;
576 9826fd59 Gerd Hoffmann
577 9826fd59 Gerd Hoffmann
    if (s->wakeup) {
578 9826fd59 Gerd Hoffmann
        qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
579 9826fd59 Gerd Hoffmann
    }
580 81174dae aliguori
    if(s->fcr & UART_FCR_FE) {
581 81174dae aliguori
        int i;
582 81174dae aliguori
        for (i = 0; i < size; i++) {
583 81174dae aliguori
            fifo_put(s, RECV_FIFO, buf[i]);
584 81174dae aliguori
        }
585 81174dae aliguori
        s->lsr |= UART_LSR_DR;
586 81174dae aliguori
        /* call the timeout receive callback in 4 char transmit time */
587 74475455 Paolo Bonzini
        qemu_mod_timer(s->fifo_timeout_timer, qemu_get_clock_ns (vm_clock) + s->char_transmit_time * 4);
588 81174dae aliguori
    } else {
589 71e605f8 Justin T. Gibbs
        if (s->lsr & UART_LSR_DR)
590 71e605f8 Justin T. Gibbs
            s->lsr |= UART_LSR_OE;
591 81174dae aliguori
        s->rbr = buf[0];
592 81174dae aliguori
        s->lsr |= UART_LSR_DR;
593 81174dae aliguori
    }
594 81174dae aliguori
    serial_update_irq(s);
595 b41a2cd1 bellard
}
596 80cabfad bellard
597 82c643ff bellard
static void serial_event(void *opaque, int event)
598 82c643ff bellard
{
599 82c643ff bellard
    SerialState *s = opaque;
600 b6601141 Michal Novotny
    DPRINTF("event %x\n", event);
601 82c643ff bellard
    if (event == CHR_EVENT_BREAK)
602 82c643ff bellard
        serial_receive_break(s);
603 82c643ff bellard
}
604 82c643ff bellard
605 d4bfa4d7 Juan Quintela
static void serial_pre_save(void *opaque)
606 8738a8d0 bellard
{
607 d4bfa4d7 Juan Quintela
    SerialState *s = opaque;
608 747791f1 Juan Quintela
    s->fcr_vmstate = s->fcr;
609 8738a8d0 bellard
}
610 8738a8d0 bellard
611 e59fb374 Juan Quintela
static int serial_post_load(void *opaque, int version_id)
612 747791f1 Juan Quintela
{
613 747791f1 Juan Quintela
    SerialState *s = opaque;
614 81174dae aliguori
615 4c18ce94 Juan Quintela
    if (version_id < 3) {
616 4c18ce94 Juan Quintela
        s->fcr_vmstate = 0;
617 4c18ce94 Juan Quintela
    }
618 81174dae aliguori
    /* Initialize fcr via setter to perform essential side-effects */
619 5ec3a23e Alexander Graf
    serial_ioport_write(s, 0x02, s->fcr_vmstate, 1);
620 9a7c4878 Michal Novotny
    serial_update_parameters(s);
621 8738a8d0 bellard
    return 0;
622 8738a8d0 bellard
}
623 8738a8d0 bellard
624 488cb996 Gerd Hoffmann
const VMStateDescription vmstate_serial = {
625 747791f1 Juan Quintela
    .name = "serial",
626 747791f1 Juan Quintela
    .version_id = 3,
627 747791f1 Juan Quintela
    .minimum_version_id = 2,
628 747791f1 Juan Quintela
    .pre_save = serial_pre_save,
629 747791f1 Juan Quintela
    .post_load = serial_post_load,
630 747791f1 Juan Quintela
    .fields      = (VMStateField []) {
631 747791f1 Juan Quintela
        VMSTATE_UINT16_V(divider, SerialState, 2),
632 747791f1 Juan Quintela
        VMSTATE_UINT8(rbr, SerialState),
633 747791f1 Juan Quintela
        VMSTATE_UINT8(ier, SerialState),
634 747791f1 Juan Quintela
        VMSTATE_UINT8(iir, SerialState),
635 747791f1 Juan Quintela
        VMSTATE_UINT8(lcr, SerialState),
636 747791f1 Juan Quintela
        VMSTATE_UINT8(mcr, SerialState),
637 747791f1 Juan Quintela
        VMSTATE_UINT8(lsr, SerialState),
638 747791f1 Juan Quintela
        VMSTATE_UINT8(msr, SerialState),
639 747791f1 Juan Quintela
        VMSTATE_UINT8(scr, SerialState),
640 747791f1 Juan Quintela
        VMSTATE_UINT8_V(fcr_vmstate, SerialState, 3),
641 747791f1 Juan Quintela
        VMSTATE_END_OF_LIST()
642 747791f1 Juan Quintela
    }
643 747791f1 Juan Quintela
};
644 747791f1 Juan Quintela
645 b2a5160c balrog
static void serial_reset(void *opaque)
646 b2a5160c balrog
{
647 b2a5160c balrog
    SerialState *s = opaque;
648 b2a5160c balrog
649 b2a5160c balrog
    s->rbr = 0;
650 b2a5160c balrog
    s->ier = 0;
651 b2a5160c balrog
    s->iir = UART_IIR_NO_INT;
652 b2a5160c balrog
    s->lcr = 0;
653 b2a5160c balrog
    s->lsr = UART_LSR_TEMT | UART_LSR_THRE;
654 b2a5160c balrog
    s->msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS;
655 718b8aec Stefan Weil
    /* Default to 9600 baud, 1 start bit, 8 data bits, 1 stop bit, no parity. */
656 81174dae aliguori
    s->divider = 0x0C;
657 81174dae aliguori
    s->mcr = UART_MCR_OUT2;
658 b2a5160c balrog
    s->scr = 0;
659 81174dae aliguori
    s->tsr_retry = 0;
660 718b8aec Stefan Weil
    s->char_transmit_time = (get_ticks_per_sec() / 9600) * 10;
661 81174dae aliguori
    s->poll_msl = 0;
662 81174dae aliguori
663 81174dae aliguori
    fifo_clear(s,RECV_FIFO);
664 81174dae aliguori
    fifo_clear(s,XMIT_FIFO);
665 81174dae aliguori
666 74475455 Paolo Bonzini
    s->last_xmit_ts = qemu_get_clock_ns(vm_clock);
667 b2a5160c balrog
668 b2a5160c balrog
    s->thr_ipending = 0;
669 b2a5160c balrog
    s->last_break_enable = 0;
670 b2a5160c balrog
    qemu_irq_lower(s->irq);
671 b2a5160c balrog
}
672 b2a5160c balrog
673 488cb996 Gerd Hoffmann
void serial_init_core(SerialState *s)
674 81174dae aliguori
{
675 ac0be998 Gerd Hoffmann
    if (!s->chr) {
676 387f4a5a Aurelien Jarno
        fprintf(stderr, "Can't create serial device, empty char device\n");
677 387f4a5a Aurelien Jarno
        exit(1);
678 387f4a5a Aurelien Jarno
    }
679 387f4a5a Aurelien Jarno
680 74475455 Paolo Bonzini
    s->modem_status_poll = qemu_new_timer_ns(vm_clock, (QEMUTimerCB *) serial_update_msl, s);
681 81174dae aliguori
682 74475455 Paolo Bonzini
    s->fifo_timeout_timer = qemu_new_timer_ns(vm_clock, (QEMUTimerCB *) fifo_timeout_int, s);
683 a08d4367 Jan Kiszka
    qemu_register_reset(serial_reset, s);
684 81174dae aliguori
685 b47543c4 aurel32
    qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1,
686 b47543c4 aurel32
                          serial_event, s);
687 81174dae aliguori
}
688 81174dae aliguori
689 419ad672 Gerd Hoffmann
void serial_exit_core(SerialState *s)
690 419ad672 Gerd Hoffmann
{
691 419ad672 Gerd Hoffmann
    qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, NULL);
692 419ad672 Gerd Hoffmann
    qemu_unregister_reset(serial_reset, s);
693 419ad672 Gerd Hoffmann
}
694 419ad672 Gerd Hoffmann
695 038eaf82 Stefan Weil
/* Change the main reference oscillator frequency. */
696 038eaf82 Stefan Weil
void serial_set_frequency(SerialState *s, uint32_t frequency)
697 038eaf82 Stefan Weil
{
698 038eaf82 Stefan Weil
    s->baudbase = frequency;
699 038eaf82 Stefan Weil
    serial_update_parameters(s);
700 038eaf82 Stefan Weil
}
701 038eaf82 Stefan Weil
702 488cb996 Gerd Hoffmann
const MemoryRegionOps serial_io_ops = {
703 5ec3a23e Alexander Graf
    .read = serial_ioport_read,
704 5ec3a23e Alexander Graf
    .write = serial_ioport_write,
705 5ec3a23e Alexander Graf
    .impl = {
706 5ec3a23e Alexander Graf
        .min_access_size = 1,
707 5ec3a23e Alexander Graf
        .max_access_size = 1,
708 5ec3a23e Alexander Graf
    },
709 5ec3a23e Alexander Graf
    .endianness = DEVICE_LITTLE_ENDIAN,
710 a941ae45 Richard Henderson
};
711 a941ae45 Richard Henderson
712 b6cd0ea1 aurel32
SerialState *serial_init(int base, qemu_irq irq, int baudbase,
713 568fd159 Julien Grall
                         CharDriverState *chr, MemoryRegion *system_io)
714 b41a2cd1 bellard
{
715 b41a2cd1 bellard
    SerialState *s;
716 b41a2cd1 bellard
717 7267c094 Anthony Liguori
    s = g_malloc0(sizeof(SerialState));
718 6936bfe5 aurel32
719 ac0be998 Gerd Hoffmann
    s->irq = irq;
720 ac0be998 Gerd Hoffmann
    s->baudbase = baudbase;
721 ac0be998 Gerd Hoffmann
    s->chr = chr;
722 ac0be998 Gerd Hoffmann
    serial_init_core(s);
723 b41a2cd1 bellard
724 0be71e32 Alex Williamson
    vmstate_register(NULL, base, &vmstate_serial, s);
725 8738a8d0 bellard
726 5ec3a23e Alexander Graf
    memory_region_init_io(&s->io, &serial_io_ops, s, "serial", 8);
727 568fd159 Julien Grall
    memory_region_add_subregion(system_io, base, &s->io);
728 5ec3a23e Alexander Graf
729 b41a2cd1 bellard
    return s;
730 80cabfad bellard
}
731 e5d13e2f bellard
732 e5d13e2f bellard
/* Memory mapped interface */
733 a8170e5e Avi Kivity
static uint64_t serial_mm_read(void *opaque, hwaddr addr,
734 8e8ffc44 Richard Henderson
                               unsigned size)
735 e5d13e2f bellard
{
736 e5d13e2f bellard
    SerialState *s = opaque;
737 5ec3a23e Alexander Graf
    return serial_ioport_read(s, addr >> s->it_shift, 1);
738 e5d13e2f bellard
}
739 e5d13e2f bellard
740 a8170e5e Avi Kivity
static void serial_mm_write(void *opaque, hwaddr addr,
741 8e8ffc44 Richard Henderson
                            uint64_t value, unsigned size)
742 2d48377a Blue Swirl
{
743 2d48377a Blue Swirl
    SerialState *s = opaque;
744 8e8ffc44 Richard Henderson
    value &= ~0u >> (32 - (size * 8));
745 5ec3a23e Alexander Graf
    serial_ioport_write(s, addr >> s->it_shift, value, 1);
746 2d48377a Blue Swirl
}
747 2d48377a Blue Swirl
748 8e8ffc44 Richard Henderson
static const MemoryRegionOps serial_mm_ops[3] = {
749 8e8ffc44 Richard Henderson
    [DEVICE_NATIVE_ENDIAN] = {
750 8e8ffc44 Richard Henderson
        .read = serial_mm_read,
751 8e8ffc44 Richard Henderson
        .write = serial_mm_write,
752 8e8ffc44 Richard Henderson
        .endianness = DEVICE_NATIVE_ENDIAN,
753 8e8ffc44 Richard Henderson
    },
754 8e8ffc44 Richard Henderson
    [DEVICE_LITTLE_ENDIAN] = {
755 8e8ffc44 Richard Henderson
        .read = serial_mm_read,
756 8e8ffc44 Richard Henderson
        .write = serial_mm_write,
757 8e8ffc44 Richard Henderson
        .endianness = DEVICE_LITTLE_ENDIAN,
758 8e8ffc44 Richard Henderson
    },
759 8e8ffc44 Richard Henderson
    [DEVICE_BIG_ENDIAN] = {
760 8e8ffc44 Richard Henderson
        .read = serial_mm_read,
761 8e8ffc44 Richard Henderson
        .write = serial_mm_write,
762 8e8ffc44 Richard Henderson
        .endianness = DEVICE_BIG_ENDIAN,
763 8e8ffc44 Richard Henderson
    },
764 e5d13e2f bellard
};
765 e5d13e2f bellard
766 39186d8a Richard Henderson
SerialState *serial_mm_init(MemoryRegion *address_space,
767 a8170e5e Avi Kivity
                            hwaddr base, int it_shift,
768 39186d8a Richard Henderson
                            qemu_irq irq, int baudbase,
769 39186d8a Richard Henderson
                            CharDriverState *chr, enum device_endian end)
770 e5d13e2f bellard
{
771 e5d13e2f bellard
    SerialState *s;
772 e5d13e2f bellard
773 7267c094 Anthony Liguori
    s = g_malloc0(sizeof(SerialState));
774 81174dae aliguori
775 e5d13e2f bellard
    s->it_shift = it_shift;
776 ac0be998 Gerd Hoffmann
    s->irq = irq;
777 ac0be998 Gerd Hoffmann
    s->baudbase = baudbase;
778 ac0be998 Gerd Hoffmann
    s->chr = chr;
779 e5d13e2f bellard
780 ac0be998 Gerd Hoffmann
    serial_init_core(s);
781 0be71e32 Alex Williamson
    vmstate_register(NULL, base, &vmstate_serial, s);
782 e5d13e2f bellard
783 8e8ffc44 Richard Henderson
    memory_region_init_io(&s->io, &serial_mm_ops[end], s,
784 8e8ffc44 Richard Henderson
                          "serial", 8 << it_shift);
785 39186d8a Richard Henderson
    memory_region_add_subregion(address_space, base, &s->io);
786 2ff0c7c3 Richard Henderson
787 81174dae aliguori
    serial_update_msl(s);
788 e5d13e2f bellard
    return s;
789 e5d13e2f bellard
}