slavio_serial.c 16.8 KB
Newer Older
bellard's avatar
bellard committed
1 2 3
/*
 * QEMU Sparc SLAVIO serial port emulation
 * 
bellard's avatar
bellard committed
4
 * Copyright (c) 2003-2005 Fabrice Bellard
bellard's avatar
bellard committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#include "vl.h"
bellard's avatar
bellard committed
25
/* debug serial */
bellard's avatar
bellard committed
26 27 28 29 30
//#define DEBUG_SERIAL

/* debug keyboard */
//#define DEBUG_KBD

bellard's avatar
bellard committed
31
/* debug mouse */
bellard's avatar
bellard committed
32 33 34 35 36 37 38 39 40 41 42 43 44
//#define DEBUG_MOUSE

/*
 * This is the serial port, mouse and keyboard part of chip STP2001
 * (Slave I/O), also produced as NCR89C105. See
 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
 * 
 * The serial ports implement full AMD AM8530 or Zilog Z8530 chips,
 * mouse and keyboard ports don't implement all functions and they are
 * only asynchronous. There is no DMA.
 *
 */

45 46 47 48 49 50 51
/*
 * Modifications:
 *  2006-Aug-10  Igor Kovalenko :   Renamed KBDQueue to SERIOQueue, implemented
 *                                  serial mouse queue.
 *                                  Implemented serial mouse protocol.
 */

bellard's avatar
bellard committed
52 53 54
#ifdef DEBUG_SERIAL
#define SER_DPRINTF(fmt, args...) \
do { printf("SER: " fmt , ##args); } while (0)
55 56
#define pic_set_irq(irq, level) \
do { printf("SER: set_irq(%d): %d\n", (irq), (level)); pic_set_irq((irq),(level));} while (0)
bellard's avatar
bellard committed
57 58 59 60 61 62 63 64 65 66 67
#else
#define SER_DPRINTF(fmt, args...)
#endif
#ifdef DEBUG_KBD
#define KBD_DPRINTF(fmt, args...) \
do { printf("KBD: " fmt , ##args); } while (0)
#else
#define KBD_DPRINTF(fmt, args...)
#endif
#ifdef DEBUG_MOUSE
#define MS_DPRINTF(fmt, args...) \
68
do { printf("MSC: " fmt , ##args); } while (0)
bellard's avatar
bellard committed
69 70 71 72 73 74 75 76
#else
#define MS_DPRINTF(fmt, args...)
#endif

typedef enum {
    chn_a, chn_b,
} chn_id_t;

77 78
#define CHN_C(s) ((s)->chn == chn_b? 'b' : 'a')

bellard's avatar
bellard committed
79 80 81 82
typedef enum {
    ser, kbd, mouse,
} chn_type_t;

83
#define SERIO_QUEUE_SIZE 256
bellard's avatar
bellard committed
84 85

typedef struct {
86
    uint8_t data[SERIO_QUEUE_SIZE];
bellard's avatar
bellard committed
87
    int rptr, wptr, count;
88
} SERIOQueue;
bellard's avatar
bellard committed
89

bellard's avatar
bellard committed
90 91 92
typedef struct ChannelState {
    int irq;
    int reg;
bellard's avatar
bellard committed
93
    int rxint, txint, rxint_under_svc, txint_under_svc;
bellard's avatar
bellard committed
94 95 96
    chn_id_t chn; // this channel, A (base+4) or B (base+0)
    chn_type_t type;
    struct ChannelState *otherchn;
bellard's avatar
bellard committed
97
    uint8_t rx, tx, wregs[16], rregs[16];
98
    SERIOQueue queue;
bellard's avatar
bellard committed
99 100 101 102 103 104 105 106 107
    CharDriverState *chr;
} ChannelState;

struct SerialState {
    struct ChannelState chn[2];
};

#define SERIAL_MAXADDR 7

bellard's avatar
bellard committed
108 109 110
static void handle_kbd_command(ChannelState *s, int val);
static int serial_can_receive(void *opaque);
static void serial_receive_byte(ChannelState *s, int ch);
bellard's avatar
bellard committed
111
static inline void set_txint(ChannelState *s);
bellard's avatar
bellard committed
112 113 114 115

static void put_queue(void *opaque, int b)
{
    ChannelState *s = opaque;
116
    SERIOQueue *q = &s->queue;
bellard's avatar
bellard committed
117

118
    SER_DPRINTF("channel %c put: 0x%02x\n", CHN_C(s), b);
119
    if (q->count >= SERIO_QUEUE_SIZE)
bellard's avatar
bellard committed
120 121
        return;
    q->data[q->wptr] = b;
122
    if (++q->wptr == SERIO_QUEUE_SIZE)
bellard's avatar
bellard committed
123 124 125 126 127 128 129 130
        q->wptr = 0;
    q->count++;
    serial_receive_byte(s, 0);
}

static uint32_t get_queue(void *opaque)
{
    ChannelState *s = opaque;
131
    SERIOQueue *q = &s->queue;
bellard's avatar
bellard committed
132 133 134 135 136 137
    int val;
    
    if (q->count == 0) {
	return 0;
    } else {
        val = q->data[q->rptr];
138
        if (++q->rptr == SERIO_QUEUE_SIZE)
bellard's avatar
bellard committed
139 140 141
            q->rptr = 0;
        q->count--;
    }
142
    KBD_DPRINTF("channel %c get 0x%02x\n", CHN_C(s), val);
bellard's avatar
bellard committed
143 144 145 146 147
    if (q->count > 0)
	serial_receive_byte(s, 0);
    return val;
}

bellard's avatar
bellard committed
148
static int slavio_serial_update_irq_chn(ChannelState *s)
bellard's avatar
bellard committed
149 150 151 152 153 154
{
    if ((s->wregs[1] & 1) && // interrupts enabled
	(((s->wregs[1] & 2) && s->txint == 1) || // tx ints enabled, pending
	 ((((s->wregs[1] & 0x18) == 8) || ((s->wregs[1] & 0x18) == 0x10)) &&
	  s->rxint == 1) || // rx ints enabled, pending
	 ((s->wregs[15] & 0x80) && (s->rregs[0] & 0x80)))) { // break int e&p
bellard's avatar
bellard committed
155
        return 1;
bellard's avatar
bellard committed
156
    }
bellard's avatar
bellard committed
157 158 159 160 161 162 163 164 165 166 167
    return 0;
}

static void slavio_serial_update_irq(ChannelState *s)
{
    int irq;

    irq = slavio_serial_update_irq_chn(s);
    irq |= slavio_serial_update_irq_chn(s->otherchn);

    pic_set_irq(s->irq, irq);
bellard's avatar
bellard committed
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
}

static void slavio_serial_reset_chn(ChannelState *s)
{
    int i;

    s->reg = 0;
    for (i = 0; i < SERIAL_MAXADDR; i++) {
	s->rregs[i] = 0;
	s->wregs[i] = 0;
    }
    s->wregs[4] = 4;
    s->wregs[9] = 0xc0;
    s->wregs[11] = 8;
    s->wregs[14] = 0x30;
    s->wregs[15] = 0xf8;
    s->rregs[0] = 0x44;
    s->rregs[1] = 6;

    s->rx = s->tx = 0;
    s->rxint = s->txint = 0;
bellard's avatar
bellard committed
189
    s->rxint_under_svc = s->txint_under_svc = 0;
bellard's avatar
bellard committed
190 191 192 193 194 195 196 197 198
}

static void slavio_serial_reset(void *opaque)
{
    SerialState *s = opaque;
    slavio_serial_reset_chn(&s->chn[0]);
    slavio_serial_reset_chn(&s->chn[1]);
}

199 200 201
static inline void clr_rxint(ChannelState *s)
{
    s->rxint = 0;
bellard's avatar
bellard committed
202
    s->rxint_under_svc = 0;
203
    if (s->chn == chn_a)
204
        s->rregs[3] &= ~0x20;
205
    else
206
        s->otherchn->rregs[3] &= ~4;
bellard's avatar
bellard committed
207 208 209 210
    if (s->txint)
        set_txint(s);
    else
        s->rregs[2] = 6;
211 212 213 214 215 216
    slavio_serial_update_irq(s);
}

static inline void set_rxint(ChannelState *s)
{
    s->rxint = 1;
bellard's avatar
bellard committed
217 218
    if (!s->txint_under_svc) {
        s->rxint_under_svc = 1;
219
        if (s->chn == chn_a)
bellard's avatar
bellard committed
220
            s->rregs[3] |= 0x20;
221
        else
bellard's avatar
bellard committed
222 223 224
            s->otherchn->rregs[3] |= 4;
        s->rregs[2] = 4;
        slavio_serial_update_irq(s);
225 226 227 228 229 230
    }
}

static inline void clr_txint(ChannelState *s)
{
    s->txint = 0;
bellard's avatar
bellard committed
231
    s->txint_under_svc = 0;
232
    if (s->chn == chn_a)
233
        s->rregs[3] &= ~0x10;
234
    else
235
        s->otherchn->rregs[3] &= ~2;
bellard's avatar
bellard committed
236 237 238 239
    if (s->rxint)
        set_rxint(s);
    else
        s->rregs[2] = 6;
240 241 242 243 244 245
    slavio_serial_update_irq(s);
}

static inline void set_txint(ChannelState *s)
{
    s->txint = 1;
bellard's avatar
bellard committed
246 247
    if (!s->rxint_under_svc) {
        s->txint_under_svc = 1;
248
        if (s->chn == chn_a)
bellard's avatar
bellard committed
249
            s->rregs[3] |= 0x10;
250
        else
bellard's avatar
bellard committed
251 252 253
            s->otherchn->rregs[3] |= 2;
        s->rregs[2] = 0;
        slavio_serial_update_irq(s);
254 255 256
    }
}

257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
static void slavio_serial_update_parameters(ChannelState *s)
{
    int speed, parity, data_bits, stop_bits;
    QEMUSerialSetParams ssp;

    if (!s->chr || s->type != ser)
        return;

    if (s->wregs[4] & 1) {
        if (s->wregs[4] & 2)
            parity = 'E';
        else
            parity = 'O';
    } else {
        parity = 'N';
    }
    if ((s->wregs[4] & 0x0c) == 0x0c)
        stop_bits = 2;
    else
        stop_bits = 1;
    switch (s->wregs[5] & 0x60) {
    case 0x00:
        data_bits = 5;
        break;
    case 0x20:
        data_bits = 7;
        break;
    case 0x40:
        data_bits = 6;
        break;
    default:
    case 0x60:
        data_bits = 8;
        break;
    }
    speed = 2457600 / ((s->wregs[12] | (s->wregs[13] << 8)) + 2);
    switch (s->wregs[4] & 0xc0) {
    case 0x00:
        break;
    case 0x40:
        speed /= 16;
        break;
    case 0x80:
        speed /= 32;
        break;
    default:
    case 0xc0:
        speed /= 64;
        break;
    }
    ssp.speed = speed;
    ssp.parity = parity;
    ssp.data_bits = data_bits;
    ssp.stop_bits = stop_bits;
    SER_DPRINTF("channel %c: speed=%d parity=%c data=%d stop=%d\n", CHN_C(s),
                speed, parity, data_bits, stop_bits);
    qemu_chr_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
}

bellard's avatar
bellard committed
316
static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
bellard's avatar
bellard committed
317 318 319 320 321 322 323 324 325 326 327 328
{
    SerialState *ser = opaque;
    ChannelState *s;
    uint32_t saddr;
    int newreg, channel;

    val &= 0xff;
    saddr = (addr & 3) >> 1;
    channel = (addr & SERIAL_MAXADDR) >> 2;
    s = &ser->chn[channel];
    switch (saddr) {
    case 0:
329
	SER_DPRINTF("Write channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg, val & 0xff);
bellard's avatar
bellard committed
330 331 332 333 334 335 336
	newreg = 0;
	switch (s->reg) {
	case 0:
	    newreg = val & 7;
	    val &= 0x38;
	    switch (val) {
	    case 8:
bellard's avatar
bellard committed
337
		newreg |= 0x8;
bellard's avatar
bellard committed
338 339
		break;
	    case 0x28:
340 341 342
                clr_txint(s);
		break;
	    case 0x38:
bellard's avatar
bellard committed
343 344 345 346
                if (s->rxint_under_svc)
                    clr_rxint(s);
                else if (s->txint_under_svc)
                    clr_txint(s);
bellard's avatar
bellard committed
347 348 349 350 351
		break;
	    default:
		break;
	    }
	    break;
352 353 354 355 356 357 358 359 360 361
        case 1 ... 3:
        case 6 ... 8:
        case 10 ... 11:
        case 14 ... 15:
	    s->wregs[s->reg] = val;
	    break;
        case 4:
        case 5:
        case 12:
        case 13:
bellard's avatar
bellard committed
362
	    s->wregs[s->reg] = val;
363
            slavio_serial_update_parameters(s);
bellard's avatar
bellard committed
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389
	    break;
	case 9:
	    switch (val & 0xc0) {
	    case 0:
	    default:
		break;
	    case 0x40:
		slavio_serial_reset_chn(&ser->chn[1]);
		return;
	    case 0x80:
		slavio_serial_reset_chn(&ser->chn[0]);
		return;
	    case 0xc0:
		slavio_serial_reset(ser);
		return;
	    }
	    break;
	default:
	    break;
	}
	if (s->reg == 0)
	    s->reg = newreg;
	else
	    s->reg = 0;
	break;
    case 1:
390
	SER_DPRINTF("Write channel %c, ch %d\n", CHN_C(s), val);
bellard's avatar
bellard committed
391 392 393 394
	if (s->wregs[5] & 8) { // tx enabled
	    s->tx = val;
	    if (s->chr)
		qemu_chr_write(s->chr, &s->tx, 1);
bellard's avatar
bellard committed
395 396 397
	    else if (s->type == kbd) {
		handle_kbd_command(s, val);
	    }
bellard's avatar
bellard committed
398 399
	    s->rregs[0] |= 4; // Tx buffer empty
	    s->rregs[1] |= 1; // All sent
400
            set_txint(s);
bellard's avatar
bellard committed
401 402 403 404 405 406 407
	}
	break;
    default:
	break;
    }
}

bellard's avatar
bellard committed
408
static uint32_t slavio_serial_mem_readb(void *opaque, target_phys_addr_t addr)
bellard's avatar
bellard committed
409 410 411 412 413 414 415 416 417 418 419 420
{
    SerialState *ser = opaque;
    ChannelState *s;
    uint32_t saddr;
    uint32_t ret;
    int channel;

    saddr = (addr & 3) >> 1;
    channel = (addr & SERIAL_MAXADDR) >> 2;
    s = &ser->chn[channel];
    switch (saddr) {
    case 0:
421
	SER_DPRINTF("Read channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg, s->rregs[s->reg]);
bellard's avatar
bellard committed
422 423 424 425 426
	ret = s->rregs[s->reg];
	s->reg = 0;
	return ret;
    case 1:
	s->rregs[0] &= ~1;
427
        clr_rxint(s);
428
	if (s->type == kbd || s->type == mouse)
bellard's avatar
bellard committed
429 430 431
	    ret = get_queue(s);
	else
	    ret = s->rx;
432
	SER_DPRINTF("Read channel %c, ch %d\n", CHN_C(s), ret);
bellard's avatar
bellard committed
433
	return ret;
bellard's avatar
bellard committed
434 435 436 437 438 439 440 441 442
    default:
	break;
    }
    return 0;
}

static int serial_can_receive(void *opaque)
{
    ChannelState *s = opaque;
bellard's avatar
bellard committed
443 444
    int ret;

bellard's avatar
bellard committed
445 446
    if (((s->wregs[3] & 1) == 0) // Rx not enabled
	|| ((s->rregs[0] & 1) == 1)) // char already available
bellard's avatar
bellard committed
447
	ret = 0;
bellard's avatar
bellard committed
448
    else
bellard's avatar
bellard committed
449
	ret = 1;
450
    //SER_DPRINTF("channel %c can receive %d\n", CHN_C(s), ret);
bellard's avatar
bellard committed
451
    return ret;
bellard's avatar
bellard committed
452 453 454 455
}

static void serial_receive_byte(ChannelState *s, int ch)
{
456
    SER_DPRINTF("channel %c put ch %d\n", CHN_C(s), ch);
bellard's avatar
bellard committed
457 458
    s->rregs[0] |= 1;
    s->rx = ch;
459
    set_rxint(s);
bellard's avatar
bellard committed
460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498
}

static void serial_receive_break(ChannelState *s)
{
    s->rregs[0] |= 0x80;
    slavio_serial_update_irq(s);
}

static void serial_receive1(void *opaque, const uint8_t *buf, int size)
{
    ChannelState *s = opaque;
    serial_receive_byte(s, buf[0]);
}

static void serial_event(void *opaque, int event)
{
    ChannelState *s = opaque;
    if (event == CHR_EVENT_BREAK)
        serial_receive_break(s);
}

static CPUReadMemoryFunc *slavio_serial_mem_read[3] = {
    slavio_serial_mem_readb,
    slavio_serial_mem_readb,
    slavio_serial_mem_readb,
};

static CPUWriteMemoryFunc *slavio_serial_mem_write[3] = {
    slavio_serial_mem_writeb,
    slavio_serial_mem_writeb,
    slavio_serial_mem_writeb,
};

static void slavio_serial_save_chn(QEMUFile *f, ChannelState *s)
{
    qemu_put_be32s(f, &s->irq);
    qemu_put_be32s(f, &s->reg);
    qemu_put_be32s(f, &s->rxint);
    qemu_put_be32s(f, &s->txint);
bellard's avatar
bellard committed
499 500
    qemu_put_be32s(f, &s->rxint_under_svc);
    qemu_put_be32s(f, &s->txint_under_svc);
bellard's avatar
bellard committed
501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516
    qemu_put_8s(f, &s->rx);
    qemu_put_8s(f, &s->tx);
    qemu_put_buffer(f, s->wregs, 16);
    qemu_put_buffer(f, s->rregs, 16);
}

static void slavio_serial_save(QEMUFile *f, void *opaque)
{
    SerialState *s = opaque;

    slavio_serial_save_chn(f, &s->chn[0]);
    slavio_serial_save_chn(f, &s->chn[1]);
}

static int slavio_serial_load_chn(QEMUFile *f, ChannelState *s, int version_id)
{
bellard's avatar
bellard committed
517
    if (version_id > 2)
bellard's avatar
bellard committed
518 519 520 521 522 523
        return -EINVAL;

    qemu_get_be32s(f, &s->irq);
    qemu_get_be32s(f, &s->reg);
    qemu_get_be32s(f, &s->rxint);
    qemu_get_be32s(f, &s->txint);
bellard's avatar
bellard committed
524 525 526 527
    if (version_id >= 2) {
        qemu_get_be32s(f, &s->rxint_under_svc);
        qemu_get_be32s(f, &s->txint_under_svc);
    }
bellard's avatar
bellard committed
528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549
    qemu_get_8s(f, &s->rx);
    qemu_get_8s(f, &s->tx);
    qemu_get_buffer(f, s->wregs, 16);
    qemu_get_buffer(f, s->rregs, 16);
    return 0;
}

static int slavio_serial_load(QEMUFile *f, void *opaque, int version_id)
{
    SerialState *s = opaque;
    int ret;

    ret = slavio_serial_load_chn(f, &s->chn[0], version_id);
    if (ret != 0)
	return ret;
    ret = slavio_serial_load_chn(f, &s->chn[1], version_id);
    return ret;

}

SerialState *slavio_serial_init(int base, int irq, CharDriverState *chr1, CharDriverState *chr2)
{
bellard's avatar
bellard committed
550
    int slavio_serial_io_memory, i;
bellard's avatar
bellard committed
551 552 553 554 555 556 557 558 559
    SerialState *s;

    s = qemu_mallocz(sizeof(SerialState));
    if (!s)
        return NULL;

    slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read, slavio_serial_mem_write, s);
    cpu_register_physical_memory(base, SERIAL_MAXADDR, slavio_serial_io_memory);

bellard's avatar
bellard committed
560 561 562 563 564 565 566 567
    s->chn[0].chr = chr1;
    s->chn[1].chr = chr2;

    for (i = 0; i < 2; i++) {
	s->chn[i].irq = irq;
	s->chn[i].chn = 1 - i;
	s->chn[i].type = ser;
	if (s->chn[i].chr) {
568 569
	    qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
                                  serial_receive1, serial_event, &s->chn[i]);
bellard's avatar
bellard committed
570
	}
bellard's avatar
bellard committed
571
    }
bellard's avatar
bellard committed
572 573
    s->chn[0].otherchn = &s->chn[1];
    s->chn[1].otherchn = &s->chn[0];
bellard's avatar
bellard committed
574
    register_savevm("slavio_serial", base, 2, slavio_serial_save, slavio_serial_load, s);
bellard's avatar
bellard committed
575 576 577 578 579
    qemu_register_reset(slavio_serial_reset, s);
    slavio_serial_reset(s);
    return s;
}

bellard's avatar
bellard committed
580 581 582 583 584 585 586 587 588 589 590
static const uint8_t keycodes[128] = {
    127, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 43, 53,
    54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 89, 76, 77, 78,
    79, 80, 81, 82, 83, 84, 85, 86, 87, 42, 99, 88, 100, 101, 102, 103,
    104, 105, 106, 107, 108, 109, 110, 47, 19, 121, 119, 5, 6, 8, 10, 12,
    14, 16, 17, 18, 7, 98, 23, 68, 69, 70, 71, 91, 92, 93, 125, 112,
    113, 114, 94, 50, 0, 0, 124, 9, 11, 0, 0, 0, 0, 0, 0, 0,
    90, 0, 46, 22, 13, 111, 52, 20, 96, 24, 28, 74, 27, 123, 44, 66,
    0, 45, 2, 4, 48, 0, 0, 21, 0, 0, 0, 0, 0, 120, 122, 67,
};

bellard's avatar
bellard committed
591 592 593
static void sunkbd_event(void *opaque, int ch)
{
    ChannelState *s = opaque;
bellard's avatar
bellard committed
594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615
    int release = ch & 0x80;

    ch = keycodes[ch & 0x7f];
    KBD_DPRINTF("Keycode %d (%s)\n", ch, release? "release" : "press");
    put_queue(s, ch | release);
}

static void handle_kbd_command(ChannelState *s, int val)
{
    KBD_DPRINTF("Command %d\n", val);
    switch (val) {
    case 1: // Reset, return type code
	put_queue(s, 0xff);
	put_queue(s, 5); // Type 5
	break;
    case 7: // Query layout
	put_queue(s, 0xfe);
	put_queue(s, 0x20); // XXX, layout?
	break;
    default:
	break;
    }
bellard's avatar
bellard committed
616 617 618 619 620 621 622 623
}

static void sunmouse_event(void *opaque, 
                               int dx, int dy, int dz, int buttons_state)
{
    ChannelState *s = opaque;
    int ch;

bellard's avatar
bellard committed
624 625 626
    /* XXX: SDL sometimes generates nul events: we delete them */
    if (dx == 0 && dy == 0 && dz == 0 && buttons_state == 0)
        return;
627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661
    MS_DPRINTF("dx=%d dy=%d buttons=%01x\n", dx, dy, buttons_state);

    ch = 0x80 | 0x7; /* protocol start byte, no buttons pressed */

    if (buttons_state & MOUSE_EVENT_LBUTTON)
        ch ^= 0x4;
    if (buttons_state & MOUSE_EVENT_MBUTTON)
        ch ^= 0x2;
    if (buttons_state & MOUSE_EVENT_RBUTTON)
        ch ^= 0x1;

    put_queue(s, ch);

    ch = dx;

    if (ch > 127)
        ch=127;
    else if (ch < -127)
        ch=-127;

    put_queue(s, ch & 0xff);

    ch = -dy;

    if (ch > 127)
        ch=127;
    else if (ch < -127)
        ch=-127;

    put_queue(s, ch & 0xff);

    // MSC protocol specify two extra motion bytes

    put_queue(s, 0);
    put_queue(s, 0);
bellard's avatar
bellard committed
662 663 664 665
}

void slavio_serial_ms_kbd_init(int base, int irq)
{
bellard's avatar
bellard committed
666
    int slavio_serial_io_memory, i;
bellard's avatar
bellard committed
667 668 669 670 671
    SerialState *s;

    s = qemu_mallocz(sizeof(SerialState));
    if (!s)
        return;
bellard's avatar
bellard committed
672 673 674 675 676 677 678 679 680
    for (i = 0; i < 2; i++) {
	s->chn[i].irq = irq;
	s->chn[i].chn = 1 - i;
	s->chn[i].chr = NULL;
    }
    s->chn[0].otherchn = &s->chn[1];
    s->chn[1].otherchn = &s->chn[0];
    s->chn[0].type = mouse;
    s->chn[1].type = kbd;
bellard's avatar
bellard committed
681 682 683 684

    slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read, slavio_serial_mem_write, s);
    cpu_register_physical_memory(base, SERIAL_MAXADDR, slavio_serial_io_memory);

685
    qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0, "QEMU Sun Mouse");
bellard's avatar
bellard committed
686
    qemu_add_kbd_event_handler(sunkbd_event, &s->chn[1]);
bellard's avatar
bellard committed
687 688 689
    qemu_register_reset(slavio_serial_reset, s);
    slavio_serial_reset(s);
}