Statistics
| Branch: | Revision:

root / hw / slavio_serial.c @ 977d5710

History | View | Annotate | Download (8.8 kB)

1 e80cfcfc bellard
/*
2 e80cfcfc bellard
 * QEMU Sparc SLAVIO serial port emulation
3 e80cfcfc bellard
 * 
4 e80cfcfc bellard
 * Copyright (c) 2003-2004 Fabrice Bellard
5 e80cfcfc bellard
 * 
6 e80cfcfc bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 e80cfcfc bellard
 * of this software and associated documentation files (the "Software"), to deal
8 e80cfcfc bellard
 * in the Software without restriction, including without limitation the rights
9 e80cfcfc bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 e80cfcfc bellard
 * copies of the Software, and to permit persons to whom the Software is
11 e80cfcfc bellard
 * furnished to do so, subject to the following conditions:
12 e80cfcfc bellard
 *
13 e80cfcfc bellard
 * The above copyright notice and this permission notice shall be included in
14 e80cfcfc bellard
 * all copies or substantial portions of the Software.
15 e80cfcfc bellard
 *
16 e80cfcfc bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 e80cfcfc bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 e80cfcfc bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 e80cfcfc bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 e80cfcfc bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 e80cfcfc bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 e80cfcfc bellard
 * THE SOFTWARE.
23 e80cfcfc bellard
 */
24 e80cfcfc bellard
#include "vl.h"
25 e80cfcfc bellard
26 e80cfcfc bellard
//#define DEBUG_SERIAL
27 e80cfcfc bellard
28 e80cfcfc bellard
/* debug keyboard */
29 e80cfcfc bellard
//#define DEBUG_KBD
30 e80cfcfc bellard
31 e80cfcfc bellard
/* debug keyboard : only mouse */
32 e80cfcfc bellard
//#define DEBUG_MOUSE
33 e80cfcfc bellard
34 e80cfcfc bellard
/*
35 e80cfcfc bellard
 * This is the serial port, mouse and keyboard part of chip STP2001
36 e80cfcfc bellard
 * (Slave I/O), also produced as NCR89C105. See
37 e80cfcfc bellard
 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
38 e80cfcfc bellard
 * 
39 e80cfcfc bellard
 * The serial ports implement full AMD AM8530 or Zilog Z8530 chips,
40 e80cfcfc bellard
 * mouse and keyboard ports don't implement all functions and they are
41 e80cfcfc bellard
 * only asynchronous. There is no DMA.
42 e80cfcfc bellard
 *
43 e80cfcfc bellard
 */
44 e80cfcfc bellard
45 e80cfcfc bellard
typedef struct ChannelState {
46 e80cfcfc bellard
    int irq;
47 e80cfcfc bellard
    int reg;
48 e80cfcfc bellard
    int rxint, txint;
49 e80cfcfc bellard
    uint8_t rx, tx, wregs[16], rregs[16];
50 e80cfcfc bellard
    CharDriverState *chr;
51 e80cfcfc bellard
} ChannelState;
52 e80cfcfc bellard
53 e80cfcfc bellard
struct SerialState {
54 e80cfcfc bellard
    struct ChannelState chn[2];
55 e80cfcfc bellard
};
56 e80cfcfc bellard
57 e80cfcfc bellard
#define SERIAL_MAXADDR 7
58 e80cfcfc bellard
59 e80cfcfc bellard
static void slavio_serial_update_irq(ChannelState *s)
60 e80cfcfc bellard
{
61 e80cfcfc bellard
    if ((s->wregs[1] & 1) && // interrupts enabled
62 e80cfcfc bellard
        (((s->wregs[1] & 2) && s->txint == 1) || // tx ints enabled, pending
63 e80cfcfc bellard
         ((((s->wregs[1] & 0x18) == 8) || ((s->wregs[1] & 0x18) == 0x10)) &&
64 e80cfcfc bellard
          s->rxint == 1) || // rx ints enabled, pending
65 e80cfcfc bellard
         ((s->wregs[15] & 0x80) && (s->rregs[0] & 0x80)))) { // break int e&p
66 e80cfcfc bellard
        pic_set_irq(s->irq, 1);
67 e80cfcfc bellard
    } else {
68 e80cfcfc bellard
        pic_set_irq(s->irq, 0);
69 e80cfcfc bellard
    }
70 e80cfcfc bellard
}
71 e80cfcfc bellard
72 e80cfcfc bellard
static void slavio_serial_reset_chn(ChannelState *s)
73 e80cfcfc bellard
{
74 e80cfcfc bellard
    int i;
75 e80cfcfc bellard
76 e80cfcfc bellard
    s->reg = 0;
77 e80cfcfc bellard
    for (i = 0; i < SERIAL_MAXADDR; i++) {
78 e80cfcfc bellard
        s->rregs[i] = 0;
79 e80cfcfc bellard
        s->wregs[i] = 0;
80 e80cfcfc bellard
    }
81 e80cfcfc bellard
    s->wregs[4] = 4;
82 e80cfcfc bellard
    s->wregs[9] = 0xc0;
83 e80cfcfc bellard
    s->wregs[11] = 8;
84 e80cfcfc bellard
    s->wregs[14] = 0x30;
85 e80cfcfc bellard
    s->wregs[15] = 0xf8;
86 e80cfcfc bellard
    s->rregs[0] = 0x44;
87 e80cfcfc bellard
    s->rregs[1] = 6;
88 e80cfcfc bellard
89 e80cfcfc bellard
    s->rx = s->tx = 0;
90 e80cfcfc bellard
    s->rxint = s->txint = 0;
91 e80cfcfc bellard
}
92 e80cfcfc bellard
93 e80cfcfc bellard
static void slavio_serial_reset(void *opaque)
94 e80cfcfc bellard
{
95 e80cfcfc bellard
    SerialState *s = opaque;
96 e80cfcfc bellard
    slavio_serial_reset_chn(&s->chn[0]);
97 e80cfcfc bellard
    slavio_serial_reset_chn(&s->chn[1]);
98 e80cfcfc bellard
}
99 e80cfcfc bellard
100 e80cfcfc bellard
static void slavio_serial_mem_writeb(void *opaque, uint32_t addr, uint32_t val)
101 e80cfcfc bellard
{
102 e80cfcfc bellard
    SerialState *ser = opaque;
103 e80cfcfc bellard
    ChannelState *s;
104 e80cfcfc bellard
    uint32_t saddr;
105 e80cfcfc bellard
    int newreg, channel;
106 e80cfcfc bellard
107 e80cfcfc bellard
    val &= 0xff;
108 e80cfcfc bellard
    saddr = (addr & 3) >> 1;
109 e80cfcfc bellard
    channel = (addr & SERIAL_MAXADDR) >> 2;
110 e80cfcfc bellard
    s = &ser->chn[channel];
111 e80cfcfc bellard
    switch (saddr) {
112 e80cfcfc bellard
    case 0:
113 e80cfcfc bellard
        newreg = 0;
114 e80cfcfc bellard
        switch (s->reg) {
115 e80cfcfc bellard
        case 0:
116 e80cfcfc bellard
            newreg = val & 7;
117 e80cfcfc bellard
            val &= 0x38;
118 e80cfcfc bellard
            switch (val) {
119 e80cfcfc bellard
            case 8:
120 e80cfcfc bellard
                s->reg |= 0x8;
121 e80cfcfc bellard
                break;
122 e80cfcfc bellard
            case 0x20:
123 e80cfcfc bellard
                s->rxint = 0;
124 e80cfcfc bellard
                break;
125 e80cfcfc bellard
            case 0x28:
126 e80cfcfc bellard
                s->txint = 0;
127 e80cfcfc bellard
                break;
128 e80cfcfc bellard
            default:
129 e80cfcfc bellard
                break;
130 e80cfcfc bellard
            }
131 e80cfcfc bellard
            break;
132 e80cfcfc bellard
        case 1 ... 8:
133 e80cfcfc bellard
        case 10 ... 15:
134 e80cfcfc bellard
            s->wregs[s->reg] = val;
135 e80cfcfc bellard
            break;
136 e80cfcfc bellard
        case 9:
137 e80cfcfc bellard
            switch (val & 0xc0) {
138 e80cfcfc bellard
            case 0:
139 e80cfcfc bellard
            default:
140 e80cfcfc bellard
                break;
141 e80cfcfc bellard
            case 0x40:
142 e80cfcfc bellard
                slavio_serial_reset_chn(&ser->chn[1]);
143 e80cfcfc bellard
                return;
144 e80cfcfc bellard
            case 0x80:
145 e80cfcfc bellard
                slavio_serial_reset_chn(&ser->chn[0]);
146 e80cfcfc bellard
                return;
147 e80cfcfc bellard
            case 0xc0:
148 e80cfcfc bellard
                slavio_serial_reset(ser);
149 e80cfcfc bellard
                return;
150 e80cfcfc bellard
            }
151 e80cfcfc bellard
            break;
152 e80cfcfc bellard
        default:
153 e80cfcfc bellard
            break;
154 e80cfcfc bellard
        }
155 e80cfcfc bellard
        if (s->reg == 0)
156 e80cfcfc bellard
            s->reg = newreg;
157 e80cfcfc bellard
        else
158 e80cfcfc bellard
            s->reg = 0;
159 e80cfcfc bellard
        break;
160 e80cfcfc bellard
    case 1:
161 e80cfcfc bellard
        if (s->wregs[5] & 8) { // tx enabled
162 e80cfcfc bellard
            s->tx = val;
163 e80cfcfc bellard
            if (s->chr)
164 e80cfcfc bellard
                qemu_chr_write(s->chr, &s->tx, 1);
165 e80cfcfc bellard
            s->txint = 1;
166 e80cfcfc bellard
        }
167 e80cfcfc bellard
        break;
168 e80cfcfc bellard
    default:
169 e80cfcfc bellard
        break;
170 e80cfcfc bellard
    }
171 e80cfcfc bellard
}
172 e80cfcfc bellard
173 e80cfcfc bellard
static uint32_t slavio_serial_mem_readb(void *opaque, uint32_t addr)
174 e80cfcfc bellard
{
175 e80cfcfc bellard
    SerialState *ser = opaque;
176 e80cfcfc bellard
    ChannelState *s;
177 e80cfcfc bellard
    uint32_t saddr;
178 e80cfcfc bellard
    uint32_t ret;
179 e80cfcfc bellard
    int channel;
180 e80cfcfc bellard
181 e80cfcfc bellard
    saddr = (addr & 3) >> 1;
182 e80cfcfc bellard
    channel = (addr & SERIAL_MAXADDR) >> 2;
183 e80cfcfc bellard
    s = &ser->chn[channel];
184 e80cfcfc bellard
    switch (saddr) {
185 e80cfcfc bellard
    case 0:
186 e80cfcfc bellard
        ret = s->rregs[s->reg];
187 e80cfcfc bellard
        s->reg = 0;
188 e80cfcfc bellard
        return ret;
189 e80cfcfc bellard
    case 1:
190 e80cfcfc bellard
        s->rregs[0] &= ~1;
191 e80cfcfc bellard
        return s->rx;
192 e80cfcfc bellard
    default:
193 e80cfcfc bellard
        break;
194 e80cfcfc bellard
    }
195 e80cfcfc bellard
    return 0;
196 e80cfcfc bellard
}
197 e80cfcfc bellard
198 e80cfcfc bellard
static int serial_can_receive(void *opaque)
199 e80cfcfc bellard
{
200 e80cfcfc bellard
    ChannelState *s = opaque;
201 e80cfcfc bellard
    if (((s->wregs[3] & 1) == 0) // Rx not enabled
202 e80cfcfc bellard
        || ((s->rregs[0] & 1) == 1)) // char already available
203 e80cfcfc bellard
        return 0;
204 e80cfcfc bellard
    else
205 e80cfcfc bellard
        return 1;
206 e80cfcfc bellard
}
207 e80cfcfc bellard
208 e80cfcfc bellard
static void serial_receive_byte(ChannelState *s, int ch)
209 e80cfcfc bellard
{
210 e80cfcfc bellard
    s->rregs[0] |= 1;
211 e80cfcfc bellard
    s->rx = ch;
212 e80cfcfc bellard
    s->rxint = 1;
213 e80cfcfc bellard
    slavio_serial_update_irq(s);
214 e80cfcfc bellard
}
215 e80cfcfc bellard
216 e80cfcfc bellard
static void serial_receive_break(ChannelState *s)
217 e80cfcfc bellard
{
218 e80cfcfc bellard
    s->rregs[0] |= 0x80;
219 e80cfcfc bellard
    slavio_serial_update_irq(s);
220 e80cfcfc bellard
}
221 e80cfcfc bellard
222 e80cfcfc bellard
static void serial_receive1(void *opaque, const uint8_t *buf, int size)
223 e80cfcfc bellard
{
224 e80cfcfc bellard
    ChannelState *s = opaque;
225 e80cfcfc bellard
    serial_receive_byte(s, buf[0]);
226 e80cfcfc bellard
}
227 e80cfcfc bellard
228 e80cfcfc bellard
static void serial_event(void *opaque, int event)
229 e80cfcfc bellard
{
230 e80cfcfc bellard
    ChannelState *s = opaque;
231 e80cfcfc bellard
    if (event == CHR_EVENT_BREAK)
232 e80cfcfc bellard
        serial_receive_break(s);
233 e80cfcfc bellard
}
234 e80cfcfc bellard
235 e80cfcfc bellard
static CPUReadMemoryFunc *slavio_serial_mem_read[3] = {
236 e80cfcfc bellard
    slavio_serial_mem_readb,
237 e80cfcfc bellard
    slavio_serial_mem_readb,
238 e80cfcfc bellard
    slavio_serial_mem_readb,
239 e80cfcfc bellard
};
240 e80cfcfc bellard
241 e80cfcfc bellard
static CPUWriteMemoryFunc *slavio_serial_mem_write[3] = {
242 e80cfcfc bellard
    slavio_serial_mem_writeb,
243 e80cfcfc bellard
    slavio_serial_mem_writeb,
244 e80cfcfc bellard
    slavio_serial_mem_writeb,
245 e80cfcfc bellard
};
246 e80cfcfc bellard
247 e80cfcfc bellard
static void slavio_serial_save_chn(QEMUFile *f, ChannelState *s)
248 e80cfcfc bellard
{
249 e80cfcfc bellard
    qemu_put_be32s(f, &s->irq);
250 e80cfcfc bellard
    qemu_put_be32s(f, &s->reg);
251 e80cfcfc bellard
    qemu_put_be32s(f, &s->rxint);
252 e80cfcfc bellard
    qemu_put_be32s(f, &s->txint);
253 e80cfcfc bellard
    qemu_put_8s(f, &s->rx);
254 e80cfcfc bellard
    qemu_put_8s(f, &s->tx);
255 e80cfcfc bellard
    qemu_put_buffer(f, s->wregs, 16);
256 e80cfcfc bellard
    qemu_put_buffer(f, s->rregs, 16);
257 e80cfcfc bellard
}
258 e80cfcfc bellard
259 e80cfcfc bellard
static void slavio_serial_save(QEMUFile *f, void *opaque)
260 e80cfcfc bellard
{
261 e80cfcfc bellard
    SerialState *s = opaque;
262 e80cfcfc bellard
263 e80cfcfc bellard
    slavio_serial_save_chn(f, &s->chn[0]);
264 e80cfcfc bellard
    slavio_serial_save_chn(f, &s->chn[1]);
265 e80cfcfc bellard
}
266 e80cfcfc bellard
267 e80cfcfc bellard
static int slavio_serial_load_chn(QEMUFile *f, ChannelState *s, int version_id)
268 e80cfcfc bellard
{
269 e80cfcfc bellard
    if (version_id != 1)
270 e80cfcfc bellard
        return -EINVAL;
271 e80cfcfc bellard
272 e80cfcfc bellard
    qemu_get_be32s(f, &s->irq);
273 e80cfcfc bellard
    qemu_get_be32s(f, &s->reg);
274 e80cfcfc bellard
    qemu_get_be32s(f, &s->rxint);
275 e80cfcfc bellard
    qemu_get_be32s(f, &s->txint);
276 e80cfcfc bellard
    qemu_get_8s(f, &s->rx);
277 e80cfcfc bellard
    qemu_get_8s(f, &s->tx);
278 e80cfcfc bellard
    qemu_get_buffer(f, s->wregs, 16);
279 e80cfcfc bellard
    qemu_get_buffer(f, s->rregs, 16);
280 e80cfcfc bellard
    return 0;
281 e80cfcfc bellard
}
282 e80cfcfc bellard
283 e80cfcfc bellard
static int slavio_serial_load(QEMUFile *f, void *opaque, int version_id)
284 e80cfcfc bellard
{
285 e80cfcfc bellard
    SerialState *s = opaque;
286 e80cfcfc bellard
    int ret;
287 e80cfcfc bellard
288 e80cfcfc bellard
    ret = slavio_serial_load_chn(f, &s->chn[0], version_id);
289 e80cfcfc bellard
    if (ret != 0)
290 e80cfcfc bellard
        return ret;
291 e80cfcfc bellard
    ret = slavio_serial_load_chn(f, &s->chn[1], version_id);
292 e80cfcfc bellard
    return ret;
293 e80cfcfc bellard
294 e80cfcfc bellard
}
295 e80cfcfc bellard
296 e80cfcfc bellard
SerialState *slavio_serial_init(int base, int irq, CharDriverState *chr1, CharDriverState *chr2)
297 e80cfcfc bellard
{
298 e80cfcfc bellard
    int slavio_serial_io_memory;
299 e80cfcfc bellard
    SerialState *s;
300 e80cfcfc bellard
301 e80cfcfc bellard
    s = qemu_mallocz(sizeof(SerialState));
302 e80cfcfc bellard
    if (!s)
303 e80cfcfc bellard
        return NULL;
304 e80cfcfc bellard
    s->chn[0].irq = irq;
305 e80cfcfc bellard
    s->chn[1].irq = irq;
306 e80cfcfc bellard
    s->chn[0].chr = chr1;
307 e80cfcfc bellard
    s->chn[1].chr = chr2;
308 e80cfcfc bellard
309 e80cfcfc bellard
    slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read, slavio_serial_mem_write, s);
310 e80cfcfc bellard
    cpu_register_physical_memory(base, SERIAL_MAXADDR, slavio_serial_io_memory);
311 e80cfcfc bellard
312 e80cfcfc bellard
    if (chr1) {
313 e80cfcfc bellard
        qemu_chr_add_read_handler(chr1, serial_can_receive, serial_receive1, &s->chn[0]);
314 e80cfcfc bellard
        qemu_chr_add_event_handler(chr1, serial_event);
315 e80cfcfc bellard
    }
316 e80cfcfc bellard
    if (chr2) {
317 e80cfcfc bellard
        qemu_chr_add_read_handler(chr2, serial_can_receive, serial_receive1, &s->chn[1]);
318 e80cfcfc bellard
        qemu_chr_add_event_handler(chr2, serial_event);
319 e80cfcfc bellard
    }
320 e80cfcfc bellard
    register_savevm("slavio_serial", base, 1, slavio_serial_save, slavio_serial_load, s);
321 e80cfcfc bellard
    qemu_register_reset(slavio_serial_reset, s);
322 e80cfcfc bellard
    slavio_serial_reset(s);
323 e80cfcfc bellard
    return s;
324 e80cfcfc bellard
}
325 e80cfcfc bellard
326 e80cfcfc bellard
static void sunkbd_event(void *opaque, int ch)
327 e80cfcfc bellard
{
328 e80cfcfc bellard
    ChannelState *s = opaque;
329 e80cfcfc bellard
    // XXX: PC -> Sun Type 5 translation?
330 e80cfcfc bellard
    serial_receive_byte(s, ch);
331 e80cfcfc bellard
}
332 e80cfcfc bellard
333 e80cfcfc bellard
static void sunmouse_event(void *opaque, 
334 e80cfcfc bellard
                               int dx, int dy, int dz, int buttons_state)
335 e80cfcfc bellard
{
336 e80cfcfc bellard
    ChannelState *s = opaque;
337 e80cfcfc bellard
    int ch;
338 e80cfcfc bellard
339 e80cfcfc bellard
    // XXX
340 e80cfcfc bellard
    ch = 0x42;
341 e80cfcfc bellard
    serial_receive_byte(s, ch);
342 e80cfcfc bellard
}
343 e80cfcfc bellard
344 e80cfcfc bellard
void slavio_serial_ms_kbd_init(int base, int irq)
345 e80cfcfc bellard
{
346 e80cfcfc bellard
    int slavio_serial_io_memory;
347 e80cfcfc bellard
    SerialState *s;
348 e80cfcfc bellard
349 e80cfcfc bellard
    s = qemu_mallocz(sizeof(SerialState));
350 e80cfcfc bellard
    if (!s)
351 e80cfcfc bellard
        return;
352 e80cfcfc bellard
    s->chn[0].irq = irq;
353 e80cfcfc bellard
    s->chn[1].irq = irq;
354 e80cfcfc bellard
    s->chn[0].chr = NULL;
355 e80cfcfc bellard
    s->chn[1].chr = NULL;
356 e80cfcfc bellard
357 e80cfcfc bellard
    slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read, slavio_serial_mem_write, s);
358 e80cfcfc bellard
    cpu_register_physical_memory(base, SERIAL_MAXADDR, slavio_serial_io_memory);
359 e80cfcfc bellard
360 e80cfcfc bellard
    qemu_add_kbd_event_handler(sunkbd_event, &s->chn[0]);
361 e80cfcfc bellard
    qemu_add_mouse_event_handler(sunmouse_event, &s->chn[1]);
362 e80cfcfc bellard
    qemu_register_reset(slavio_serial_reset, s);
363 e80cfcfc bellard
    slavio_serial_reset(s);
364 e80cfcfc bellard
}