source: trunk/packages/xen-3.1/xen-3.1/tools/ioemu/hw/slavio_serial.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

File size: 13.2 KB
Line 
1/*
2 * QEMU Sparc SLAVIO serial port emulation
3 *
4 * Copyright (c) 2003-2005 Fabrice Bellard
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24#include "vl.h"
25/* debug serial */
26//#define DEBUG_SERIAL
27
28/* debug keyboard */
29//#define DEBUG_KBD
30
31/* debug mouse */
32//#define DEBUG_MOUSE
33
34/*
35 * This is the serial port, mouse and keyboard part of chip STP2001
36 * (Slave I/O), also produced as NCR89C105. See
37 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
38 *
39 * The serial ports implement full AMD AM8530 or Zilog Z8530 chips,
40 * mouse and keyboard ports don't implement all functions and they are
41 * only asynchronous. There is no DMA.
42 *
43 */
44
45#ifdef DEBUG_SERIAL
46#define SER_DPRINTF(fmt, args...) \
47do { printf("SER: " fmt , ##args); } while (0)
48#define pic_set_irq(irq, level) \
49do { printf("SER: set_irq(%d): %d\n", (irq), (level)); pic_set_irq((irq),(level));} while (0)
50#else
51#define SER_DPRINTF(fmt, args...)
52#endif
53#ifdef DEBUG_KBD
54#define KBD_DPRINTF(fmt, args...) \
55do { printf("KBD: " fmt , ##args); } while (0)
56#else
57#define KBD_DPRINTF(fmt, args...)
58#endif
59#ifdef DEBUG_MOUSE
60#define MS_DPRINTF(fmt, args...) \
61do { printf("SER: " fmt , ##args); } while (0)
62#else
63#define MS_DPRINTF(fmt, args...)
64#endif
65
66typedef enum {
67    chn_a, chn_b,
68} chn_id_t;
69
70typedef enum {
71    ser, kbd, mouse,
72} chn_type_t;
73
74#define KBD_QUEUE_SIZE 256
75
76typedef struct {
77    uint8_t data[KBD_QUEUE_SIZE];
78    int rptr, wptr, count;
79} KBDQueue;
80
81typedef struct ChannelState {
82    int irq;
83    int reg;
84    int rxint, txint;
85    chn_id_t chn; // this channel, A (base+4) or B (base+0)
86    chn_type_t type;
87    struct ChannelState *otherchn;
88    uint8_t rx, tx, wregs[16], rregs[16];
89    KBDQueue queue;
90    CharDriverState *chr;
91} ChannelState;
92
93struct SerialState {
94    struct ChannelState chn[2];
95};
96
97#define SERIAL_MAXADDR 7
98
99static void handle_kbd_command(ChannelState *s, int val);
100static int serial_can_receive(void *opaque);
101static void serial_receive_byte(ChannelState *s, int ch);
102
103static void put_queue(void *opaque, int b)
104{
105    ChannelState *s = opaque;
106    KBDQueue *q = &s->queue;
107
108    KBD_DPRINTF("put: 0x%02x\n", b);
109    if (q->count >= KBD_QUEUE_SIZE)
110        return;
111    q->data[q->wptr] = b;
112    if (++q->wptr == KBD_QUEUE_SIZE)
113        q->wptr = 0;
114    q->count++;
115    serial_receive_byte(s, 0);
116}
117
118static uint32_t get_queue(void *opaque)
119{
120    ChannelState *s = opaque;
121    KBDQueue *q = &s->queue;
122    int val;
123   
124    if (q->count == 0) {
125        return 0;
126    } else {
127        val = q->data[q->rptr];
128        if (++q->rptr == KBD_QUEUE_SIZE)
129            q->rptr = 0;
130        q->count--;
131    }
132    KBD_DPRINTF("get 0x%02x\n", val);
133    if (q->count > 0)
134        serial_receive_byte(s, 0);
135    return val;
136}
137
138static void slavio_serial_update_irq(ChannelState *s)
139{
140    if ((s->wregs[1] & 1) && // interrupts enabled
141        (((s->wregs[1] & 2) && s->txint == 1) || // tx ints enabled, pending
142         ((((s->wregs[1] & 0x18) == 8) || ((s->wregs[1] & 0x18) == 0x10)) &&
143          s->rxint == 1) || // rx ints enabled, pending
144         ((s->wregs[15] & 0x80) && (s->rregs[0] & 0x80)))) { // break int e&p
145        pic_set_irq(s->irq, 1);
146    } else {
147        pic_set_irq(s->irq, 0);
148    }
149}
150
151static void slavio_serial_reset_chn(ChannelState *s)
152{
153    int i;
154
155    s->reg = 0;
156    for (i = 0; i < SERIAL_MAXADDR; i++) {
157        s->rregs[i] = 0;
158        s->wregs[i] = 0;
159    }
160    s->wregs[4] = 4;
161    s->wregs[9] = 0xc0;
162    s->wregs[11] = 8;
163    s->wregs[14] = 0x30;
164    s->wregs[15] = 0xf8;
165    s->rregs[0] = 0x44;
166    s->rregs[1] = 6;
167
168    s->rx = s->tx = 0;
169    s->rxint = s->txint = 0;
170}
171
172static void slavio_serial_reset(void *opaque)
173{
174    SerialState *s = opaque;
175    slavio_serial_reset_chn(&s->chn[0]);
176    slavio_serial_reset_chn(&s->chn[1]);
177}
178
179static inline void clr_rxint(ChannelState *s)
180{
181    s->rxint = 0;
182    if (s->chn == 0)
183        s->rregs[3] &= ~0x20;
184    else {
185        s->otherchn->rregs[3] &= ~4;
186    }
187    slavio_serial_update_irq(s);
188}
189
190static inline void set_rxint(ChannelState *s)
191{
192    s->rxint = 1;
193    if (s->chn == 0)
194        s->rregs[3] |= 0x20;
195    else {
196        s->otherchn->rregs[3] |= 4;
197    }
198    slavio_serial_update_irq(s);
199}
200
201static inline void clr_txint(ChannelState *s)
202{
203    s->txint = 0;
204    if (s->chn == 0)
205        s->rregs[3] &= ~0x10;
206    else {
207        s->otherchn->rregs[3] &= ~2;
208    }
209    slavio_serial_update_irq(s);
210}
211
212static inline void set_txint(ChannelState *s)
213{
214    s->txint = 1;
215    if (s->chn == 0)
216        s->rregs[3] |= 0x10;
217    else {
218        s->otherchn->rregs[3] |= 2;
219    }
220    slavio_serial_update_irq(s);
221}
222
223static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
224{
225    SerialState *ser = opaque;
226    ChannelState *s;
227    uint32_t saddr;
228    int newreg, channel;
229
230    val &= 0xff;
231    saddr = (addr & 3) >> 1;
232    channel = (addr & SERIAL_MAXADDR) >> 2;
233    s = &ser->chn[channel];
234    switch (saddr) {
235    case 0:
236        SER_DPRINTF("Write channel %c, reg[%d] = %2.2x\n", channel? 'b' : 'a', s->reg, val & 0xff);
237        newreg = 0;
238        switch (s->reg) {
239        case 0:
240            newreg = val & 7;
241            val &= 0x38;
242            switch (val) {
243            case 8:
244                newreg |= 0x8;
245                break;
246            case 0x20:
247                clr_rxint(s);
248                break;
249            case 0x28:
250                clr_txint(s);
251                break;
252            case 0x38:
253                clr_rxint(s);
254                clr_txint(s);
255                break;
256            default:
257                break;
258            }
259            break;
260        case 1 ... 8:
261        case 10 ... 15:
262            s->wregs[s->reg] = val;
263            break;
264        case 9:
265            switch (val & 0xc0) {
266            case 0:
267            default:
268                break;
269            case 0x40:
270                slavio_serial_reset_chn(&ser->chn[1]);
271                return;
272            case 0x80:
273                slavio_serial_reset_chn(&ser->chn[0]);
274                return;
275            case 0xc0:
276                slavio_serial_reset(ser);
277                return;
278            }
279            break;
280        default:
281            break;
282        }
283        if (s->reg == 0)
284            s->reg = newreg;
285        else
286            s->reg = 0;
287        break;
288    case 1:
289        SER_DPRINTF("Write channel %c, ch %d\n", channel? 'b' : 'a', val);
290        if (s->wregs[5] & 8) { // tx enabled
291            s->tx = val;
292            if (s->chr)
293                qemu_chr_write(s->chr, &s->tx, 1);
294            else if (s->type == kbd) {
295                handle_kbd_command(s, val);
296            }
297            s->txint = 1;
298            s->rregs[0] |= 4; // Tx buffer empty
299            s->rregs[1] |= 1; // All sent
300            set_txint(s);
301            slavio_serial_update_irq(s);
302        }
303        break;
304    default:
305        break;
306    }
307}
308
309static uint32_t slavio_serial_mem_readb(void *opaque, target_phys_addr_t addr)
310{
311    SerialState *ser = opaque;
312    ChannelState *s;
313    uint32_t saddr;
314    uint32_t ret;
315    int channel;
316
317    saddr = (addr & 3) >> 1;
318    channel = (addr & SERIAL_MAXADDR) >> 2;
319    s = &ser->chn[channel];
320    switch (saddr) {
321    case 0:
322        SER_DPRINTF("Read channel %c, reg[%d] = %2.2x\n", channel? 'b' : 'a', s->reg, s->rregs[s->reg]);
323        ret = s->rregs[s->reg];
324        s->reg = 0;
325        return ret;
326    case 1:
327        s->rregs[0] &= ~1;
328        clr_rxint(s);
329        if (s->type == kbd)
330            ret = get_queue(s);
331        else
332            ret = s->rx;
333        SER_DPRINTF("Read channel %c, ch %d\n", channel? 'b' : 'a', ret);
334        return ret;
335    default:
336        break;
337    }
338    return 0;
339}
340
341static int serial_can_receive(void *opaque)
342{
343    ChannelState *s = opaque;
344    if (((s->wregs[3] & 1) == 0) // Rx not enabled
345        || ((s->rregs[0] & 1) == 1)) // char already available
346        return 0;
347    else
348        return 1;
349}
350
351static void serial_receive_byte(ChannelState *s, int ch)
352{
353    SER_DPRINTF("put ch %d\n", ch);
354    s->rregs[0] |= 1;
355    s->rx = ch;
356    set_rxint(s);
357}
358
359static void serial_receive_break(ChannelState *s)
360{
361    s->rregs[0] |= 0x80;
362    slavio_serial_update_irq(s);
363}
364
365static void serial_receive1(void *opaque, const uint8_t *buf, int size)
366{
367    ChannelState *s = opaque;
368    serial_receive_byte(s, buf[0]);
369}
370
371static void serial_event(void *opaque, int event)
372{
373    ChannelState *s = opaque;
374    if (event == CHR_EVENT_BREAK)
375        serial_receive_break(s);
376}
377
378static CPUReadMemoryFunc *slavio_serial_mem_read[3] = {
379    slavio_serial_mem_readb,
380    slavio_serial_mem_readb,
381    slavio_serial_mem_readb,
382};
383
384static CPUWriteMemoryFunc *slavio_serial_mem_write[3] = {
385    slavio_serial_mem_writeb,
386    slavio_serial_mem_writeb,
387    slavio_serial_mem_writeb,
388};
389
390static void slavio_serial_save_chn(QEMUFile *f, ChannelState *s)
391{
392    qemu_put_be32s(f, &s->irq);
393    qemu_put_be32s(f, &s->reg);
394    qemu_put_be32s(f, &s->rxint);
395    qemu_put_be32s(f, &s->txint);
396    qemu_put_8s(f, &s->rx);
397    qemu_put_8s(f, &s->tx);
398    qemu_put_buffer(f, s->wregs, 16);
399    qemu_put_buffer(f, s->rregs, 16);
400}
401
402static void slavio_serial_save(QEMUFile *f, void *opaque)
403{
404    SerialState *s = opaque;
405
406    slavio_serial_save_chn(f, &s->chn[0]);
407    slavio_serial_save_chn(f, &s->chn[1]);
408}
409
410static int slavio_serial_load_chn(QEMUFile *f, ChannelState *s, int version_id)
411{
412    if (version_id != 1)
413        return -EINVAL;
414
415    qemu_get_be32s(f, &s->irq);
416    qemu_get_be32s(f, &s->reg);
417    qemu_get_be32s(f, &s->rxint);
418    qemu_get_be32s(f, &s->txint);
419    qemu_get_8s(f, &s->rx);
420    qemu_get_8s(f, &s->tx);
421    qemu_get_buffer(f, s->wregs, 16);
422    qemu_get_buffer(f, s->rregs, 16);
423    return 0;
424}
425
426static int slavio_serial_load(QEMUFile *f, void *opaque, int version_id)
427{
428    SerialState *s = opaque;
429    int ret;
430
431    ret = slavio_serial_load_chn(f, &s->chn[0], version_id);
432    if (ret != 0)
433        return ret;
434    ret = slavio_serial_load_chn(f, &s->chn[1], version_id);
435    return ret;
436
437}
438
439SerialState *slavio_serial_init(int base, int irq, CharDriverState *chr1, CharDriverState *chr2)
440{
441    int slavio_serial_io_memory, i;
442    SerialState *s;
443
444    s = qemu_mallocz(sizeof(SerialState));
445    if (!s)
446        return NULL;
447
448    slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read, slavio_serial_mem_write, s);
449    cpu_register_physical_memory(base, SERIAL_MAXADDR, slavio_serial_io_memory);
450
451    s->chn[0].chr = chr1;
452    s->chn[1].chr = chr2;
453
454    for (i = 0; i < 2; i++) {
455        s->chn[i].irq = irq;
456        s->chn[i].chn = 1 - i;
457        s->chn[i].type = ser;
458        if (s->chn[i].chr) {
459            qemu_chr_add_read_handler(s->chn[i].chr, serial_can_receive, serial_receive1, &s->chn[i]);
460            qemu_chr_add_event_handler(s->chn[i].chr, serial_event);
461        }
462    }
463    s->chn[0].otherchn = &s->chn[1];
464    s->chn[1].otherchn = &s->chn[0];
465    register_savevm("slavio_serial", base, 1, slavio_serial_save, slavio_serial_load, s);
466    qemu_register_reset(slavio_serial_reset, s);
467    slavio_serial_reset(s);
468    return s;
469}
470
471static const uint8_t keycodes[128] = {
472    127, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 43, 53,
473    54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 89, 76, 77, 78,
474    79, 80, 81, 82, 83, 84, 85, 86, 87, 42, 99, 88, 100, 101, 102, 103,
475    104, 105, 106, 107, 108, 109, 110, 47, 19, 121, 119, 5, 6, 8, 10, 12,
476    14, 16, 17, 18, 7, 98, 23, 68, 69, 70, 71, 91, 92, 93, 125, 112,
477    113, 114, 94, 50, 0, 0, 124, 9, 11, 0, 0, 0, 0, 0, 0, 0,
478    90, 0, 46, 22, 13, 111, 52, 20, 96, 24, 28, 74, 27, 123, 44, 66,
479    0, 45, 2, 4, 48, 0, 0, 21, 0, 0, 0, 0, 0, 120, 122, 67,
480};
481
482static void sunkbd_event(void *opaque, int ch)
483{
484    ChannelState *s = opaque;
485    int release = ch & 0x80;
486
487    ch = keycodes[ch & 0x7f];
488    KBD_DPRINTF("Keycode %d (%s)\n", ch, release? "release" : "press");
489    put_queue(s, ch | release);
490}
491
492static void handle_kbd_command(ChannelState *s, int val)
493{
494    KBD_DPRINTF("Command %d\n", val);
495    switch (val) {
496    case 1: // Reset, return type code
497        put_queue(s, 0xff);
498        put_queue(s, 5); // Type 5
499        break;
500    case 7: // Query layout
501        put_queue(s, 0xfe);
502        put_queue(s, 0x20); // XXX, layout?
503        break;
504    default:
505        break;
506    }
507}
508
509static void sunmouse_event(void *opaque, 
510                               int dx, int dy, int dz, int buttons_state)
511{
512    ChannelState *s = opaque;
513    int ch;
514
515    // XXX
516    ch = 0x42;
517    serial_receive_byte(s, ch);
518}
519
520void slavio_serial_ms_kbd_init(int base, int irq)
521{
522    int slavio_serial_io_memory, i;
523    SerialState *s;
524
525    s = qemu_mallocz(sizeof(SerialState));
526    if (!s)
527        return;
528    for (i = 0; i < 2; i++) {
529        s->chn[i].irq = irq;
530        s->chn[i].chn = 1 - i;
531        s->chn[i].chr = NULL;
532    }
533    s->chn[0].otherchn = &s->chn[1];
534    s->chn[1].otherchn = &s->chn[0];
535    s->chn[0].type = mouse;
536    s->chn[1].type = kbd;
537
538    slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read, slavio_serial_mem_write, s);
539    cpu_register_physical_memory(base, SERIAL_MAXADDR, slavio_serial_io_memory);
540
541    qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0);
542    qemu_add_kbd_event_handler(sunkbd_event, &s->chn[1]);
543    qemu_register_reset(slavio_serial_reset, s);
544    slavio_serial_reset(s);
545}
Note: See TracBrowser for help on using the repository browser.